【JZOJ5629】Map

Description
Rin是个特别好动的少女。
一天Rin来到了一个遥远的都市。这个都市有N个建筑,编号从1到N,其中市中心编号为1,这个都市有M条双向通行的街道,每条街道连接着两个不同的建筑,其中某些街道首尾相连连接成了一个环。Rin通过长时间的走访,已经清楚了这个都市的两个特点:
从市中心出发可以到达所有的建筑物。
任意一条街道最多存在与一个简单环中。令Rin心花怒放的是,每个建筑物都会有拉面售卖。拉面有很多不同的种类,但对于Rin而言只有油腻程度的不同,因此我们把油腻程度相同的拉面看做同一种拉面。由于不同建筑物的拉面的油腻程度可能不同,我们用一个正整数来表示拉面的油腻程度。
要知道,拉面可是Rin的最爱,但是现在到了下班高峰期,都市的交通变得非常的堵塞。Rin只能通过没有被堵死的街道通行,去品尝所在建筑物的拉面。
现在Rin想知道,如果她正在编号为x的建筑物,那么在从市中心到x的所有简单路径经过的街道都被堵死的情况下,Rin可以品尝到的拉面中(注意没有出现的拉面是不能算在里面的):
油腻程度<=y且品尝次数为奇数次的拉面有多少种?
油腻程度<=y且品尝次数为偶数次的拉面有多少种?

Input
第一行两个正整数N,M,含义如题所示。
第二行一共N个正整数,第i个数Ai表示第i个建筑物出售的拉面的油腻程度。
接下来M行,每行两个正整数x,y,表示在建筑物x,y之间有一条双向通行的街道。数据保证1<=x,y<=N。
接下来一行一个正整数Q,表示询问个数。
接下来Q行每行三个非负整数ty,x,y,x表示询问的建筑物编号,y表示油腻程度的限制,ty=0时表示询问偶数,ty=1表示询问奇数。

Output
一共q行,对于每个询问输出一个答案。

Sample

Input:
5 6
2 1 6 7 7
1 2
1 3
2 4
4 5
4 5
1 3
3
0 3 2
0 3 1
0 1 7
Output:
0
0
1

Data Constraint
提示:请注意数据范围中的<= ,特殊条件中提到的y均为询问中的y

Hint
3号建筑物只能到达它自己,而 1号建筑物可以到达所有建筑物。


Analysis

这是一棵仙人掌
一个很朴素的思路,破环,将环内的成员向环的起点连边
剩下的用dfs序莫队

codes

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 150100
#define M 1000001
#define S 1000
#define P 320

using namespace std;

int to[N*2],fir[N],nex[N*2],T,dfn[N],ord[N],num[M],s[2][S+5],own[N];
int n,m,p,ans[N],top=1,cnt,fa[N],til[N],val[N],las[N],sta[N];
bool bz[N],vis[N];
struct qry{int x,y,s,v,p;}q[N];
bool cmp(qry a,qry b){return own[a.x]<own[b.x] || (own[a.x]==own[b.x] && a.y<b.y);}

void link(int x,int y){
    to[++top]=y;nex[top]=fir[x];fir[x]=top;
}

void dg(int w,int dad){
    if(vis[w]){
        for(int i=top;sta[i]!=w;i--)fa[sta[i]]=w;
        return;
    }
    vis[sta[++top]=w]=1;las[w]=dad;
    for(int i=fir[w];i;i=nex[i])if(!bz[i/2]){
        bz[i/2]=1;dg(to[i],w);
    }--top;
}
void dfs(int w){
    ord[dfn[w]=++cnt]=w;til[w]=dfn[w];
    for(int i=fir[w];i;i=nex[i])dfs(to[i]),til[w]=max(til[w],til[to[i]]);
}

void put(int v){
    num[v]++;int k=(v-1)/S+1,p=num[v]&1;
    s[1][k]+=p*2-1;if(num[v]>1)s[0][k]+=1-2*p;
}
void take(int v){
    num[v]--;int k=(v-1)/S+1,p=num[v]&1;
    s[1][k]+=p*2-1;if(num[v])s[0][k]+=1-2*p;
}
int query(int tp,int v){
    int r=0,p,i;
    for(i=1,p=S;p<v;i++,p+=S)r+=s[tp][i];
    for(p-=S-1;p<=v;p++)r+=(num[p])&&(num[p]%2==tp);
    return r;
}

int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&val[i]),own[i]=(i-1)/P+1;
    for(int i=1;i<=m;i++){
        int x,y;scanf("%d %d",&x,&y);link(x,y);link(y,x);
    }top=0;dg(1,0);top=0;
    for(int i=1;i<=n;i++)if(!fa[i])fa[i]=las[i];
    for(int i=1;i<=n;i++)fir[i]=0;
    for(int i=2;i<=n;i++)link(fa[i],i);
    dfs(1);scanf("%d",&p);
    for(int i=1;i<=p;i++){
        int x,s,v;scanf("%d %d %d",&s,&x,&v);
        q[i]=(qry){dfn[x],til[x],s,v,i};
    }sort(q+1,q+p+1,cmp);
    for(int i=1,l=1,r=0;i<=p;i++){
        int x=q[i].x,y=q[i].y,v=q[i].v,s=q[i].s;
        while(x<l)put(val[ord[--l]]);while(y>r)put(val[ord[++r]]);
        while(x>l)take(val[ord[l++]]);while(y<r)take(val[ord[r--]]);
        ans[q[i].p]=query(s,v);
    }
    for(int i=1;i<=p;i++)printf("%d\n",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/white_elephant/article/details/80342207
Map
今日推荐