Description
Rin is a particularly well-moving maiden.
One day Rin came to a distant city. The city has n buildings numbered from 1 to N, of which the city centre is numbered 1, the city has M-Way street, and each street is connected to two different buildings, some of which are connected together in a ring. Rin has been clear about the two characteristics of the city through a long visit:
All the buildings can be reached from the city centre.
Any street exists at most with a simple ring. What makes Rin so elated is that every building will have ramen noodles for sale. There are many different types of ramen, but for Rin it is only greasy, so we treat ramen with the same greasy level as the same ramen. Because ramen in different buildings may have different levels of greasy, we use a positive integer to indicate how greasy the ramen is.
You know, ramen is the favorite of Rin, but now the rush hour, the city's traffic becomes very clogged. Rin can only pass through streets that are not blocked, to taste the ramen in the building.
Now Rin wants to know if she is building the number x, then in the case where all the simple paths from the city center to X are blocked, the ramen that Rin can taste (note that the ramen that doesn't appear is not counted):
How many kinds of ramen are the greasy degree <=y and the odd number of tasting times.
How many kinds of ramen are the greasy <=y and tasting times even several times? Input
The first row of two positive integers n,m, meaning title.
The second line is a total of n positive integers, and the number I AI represents the greasy degree of ramen sold by the building I.
The next m line, two positive integers per line, x, Y, indicates a two-way street between building X, Y. Data Assurance 1<=x,y<=n.
The next line is a positive integer q, which indicates the number of queries.
The next Q line of three non-negative integer ty,x,y,x indicates the number of buildings questioned, Y represents the limit of greasy degree, ty=0 when asked even, ty=1 to ask odd. Output
A total of Q lines, for each query output an answer. 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 Sample Output
0
0
1 Data Constraint
Solution
Cactus, there is a routine to become a tree: details here to view
It's about making the top of the ring and connecting the dots on the ring to the roof. This is exactly the same as the tree.
How do the trees do it.
For each point, open a segment tree to indicate how many times each of the ramen pairs and odd number of each point, maintenance is very simple, the line tree merged a bit. Code
#include <cstdio> #include <cstring> #include <algorithm> #define FO (i,a,b) for (int i=a;i<=b;i++) #
Define N 101000 using namespace std;
int n,m,a[n],last[n],nxt[n*5],to[n*5],tot=1,fa[n],dfn[n],s[n],k;
int root[n],q[n][3],las[n],xnt[n],dat[n],son[n],sz[n],ans[n],b[n],c[n],d[1010000],qu; struct node{int l,r,d1,d2;}
T[N*70]; void Putin (int x,int y) {nxt[++tot]=last[x];last[x]=tot;to[tot]=y;} void putsin (int x,int y) {xnt[++tot]=las[x]
; las[x]=tot;dat[tot]=y;
} bool cnt (int x,int y) {return c[x]<c[y];} void Tarjan (int x,int fat) {dfn[x]=++tot;
S[++s[0]]=x;
for (int i=last[x];i;i=nxt[i]) if (i!=fat) {int y=to[i];
if (dfn[y]>0) {if (dfn[y]<dfn[x]) for (int z=s[0];s[z]!=y;z--) fa[s[z]]=y;
Continue
} Tarjan (y,i^1);
if (fa[y]==0) fa[y]=x;
} s[0]--;
} void DG (int x) {sz[x]=1;
for (int i=last[x];i;i=nxt[i]) {int y=to[i];
DG (y); Sz[x]+=sz[y];
if (Sz[y]>sz[son[x]]) son[x]=y;
}} void Add (int &x) {if (x>0) return;
X=++tot;
} void Update (int v) {t[v].d1=t[t[v].l].d1+t[t[v].r].d1;
T[V].D2=T[T[V].L].D2+T[T[V].R].D2;
} void Merge (int v1,int v2,int I,int j) {if (i==j) {int x=t[v1].d1^t[v2].d1;
if (x==0) t[v1].d1=1,t[v1].d2=0;
else t[v1].d1=0,t[v1].d2=1;
Return
} int m= (I+J)/2;
if (t[v1].l==0) t[v1].l=t[v2].l;
else if (t[v2].l>0) merge (t[v1].l,t[v2].l,i,m);
if (t[v1].r==0) T[V1].R=T[V2].R;
else if (t[v2].r>0) merge (T[V1].R,T[V2].R,M+1,J);
Update (v1);
} void Change (int v,int i,int j,int x) {if (i==j) {if (t[v].d1+t[v].d2==0) t[v].d2=1;
else t[v].d1=1-t[v].d1,t[v].d2=1-t[v].d2;
Return
} int m= (I+J)/2;
if (x<=m) Add (T[V].L), change (t[v].l,i,m,x);
else Add (T[V].R), change (t[v].r,m+1,j,x);
Update (v); } int get (int v,int i,int j,int x,int y,int z) {if (V==0) return 0;
if (i==x&&j==y) {if (z==0) return t[v].d1;
else return t[v].d2;
} int m= (I+J)/2;
if (y<=m) return get (T[V].L,I,M,X,Y,Z);
else if (x>m) return get (T[V].R,M+1,J,X,Y,Z);
else return get (t[v].l,i,m,x,m,z) +get (t[v].r,m+1,j,m+1,y,z);
} void Dfs (int x) {if (son[x]>0) {DFS (son[x]);
ROOT[X]=ROOT[SON[X]];
} else Root[x]=++tot;
for (int i=last[x];i;i=nxt[i]) {int y=to[i];
if (y==son[x]) continue;
DFS (y);
Merge (Root[x],root[y],1,k);
} change (root[x],1,k,a[x]);
for (int i=las[x];i;i=xnt[i]) {int y=dat[i];
if (Q[y][2]>c[b[n]]) d[q[y][2]]=k;
if (d[q[y][2]]>0) Ans[y]=get (root[x],1,k,1,d[q[y][2]],q[y][0]);
}} int main () {freopen ("map.in", "R", stdin);
Freopen ("Map.out", "w", stdout);
scanf ("%d%d", &n,&m);
Fo (i,1,n) scanf ("%d", &c[i]), b[i]=i;
Sort (b+1,b+n+1,cnt);
Fo (i,1,n) {if (c[b[i]]>c[b[i-1]]) k++;
Fo (j,c[b[i-1]],c[b[i]]-1) d[j]=k-1;
A[b[i]]=k;
} d[c[b[n]]]=k;
Fo (i,1,m) {int x,y;scanf ("%d%d", &x,&y);
Vladimir Putin (x, y);p utin (y,x);
} tot=0;
Tarjan (1,0);
Memset (Last,0,sizeof (last));
tot=0;
FO (i,2,n) Putin (fa[i],i);
DG (1);
tot=0;
scanf ("%d", &qu);
Fo (i,1,qu) {scanf ("%d%d%d", &q[i][0],&q[i][1],&q[i][2]);
Putsin (Q[i][1],i);
} tot=0;
DFS (1);
Fo (i,1,qu) printf ("%d\n", Ans[i]); }