HDU 5296 annoying problem
Title Link: Hdu 5296
Test instructions: In a given tree with edge, a node of the set of S (initially empty), given Q operations, each operation adds or removes a point in S, after each operation the output makes the set S a little connected to the Benquan of the small tree and.
Idea: the necessary and sufficient conditions for the nodes on the tree:
- The node is a sub-node (a bit of LCA in the S collection);
- A node has a descendant as a point in the S collection.
Then we give each node an array of tokens, initially zero, each join a node, the point from this node to the root node on the path of the value of +1, and Vice-1, so that through the query of each single node value can know if it is the most small tree node.
Then there are two scenarios for each node increment and deletion:
The first kind: adding or deleting a new node does not change the root node of the tree, then there must be a node is the ancestor of this new node, then we find this deepest ancestor in the most small tree ancestor is the key node, can multiply beg;
The second type: adding or deleting a new node changes the root node of the tree, so this key node is the root node of the old subtree.
After obtaining the key node, add or subtract the weight of the edge between two points and OK.
Code:
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <queue > #include <set> #include <algorithm> #define Lson o<<1, L,mid#define Rson o<<1|1, mid+1, rusing namespace std;Const intmaxn=120010+5;//maximum number of nodesConst intMAXM =maxn*2;//maximum number of side barsConst intDEG = -;intV[MAXM];//v[i] Indicates the node to which the edge of section I is pointingintPREV[MAXM];//prev[i] denotes the sibling side of Iinted[maxm][3];//Store the information of the EdgeintINFO[MAXN];//Indicates the last inserted edge connected to node IintQ[MAXN];//For implementing queues and stacksintIDX[MAXN];//Store node I in the chain number from leaf to root in order to increaseintDEP[MAXN];//Depth of nodeintSIZE[MAXN];//Weight of the chainintBELONG[MAXN];//Indicates the number of the edge that the node I belongs tointFATHER[MAXN];//Direct father of node IBOOL VIS[MAXN];//Mark used in Split backtrackingintHEAD[MAXN];the head node of the chain of section IintLEN[MAXN];//The length of the chain of article IintL,r,ans,cnt=0;//cnt The number of bars for the chainintN,nedge=0;//nedge is the number of bars for the edge n is the total pointintPOS[MAXN];//The location of each store after the tree chain is splitintVAL[MAXN];//Calculate the weight of the edge that the node has passed to the root node andintRK[MAXN];//Node DFS sequenceintFRK[MAXN];inverse function of//dfs sequenceintFA[MAXN][DEG];//2^j times ancestor of node I/****************** tree chain split part ****************************///Tree chain split sectionInlinevoidInsertintXintYintc) {++nedge; V[nedge]=y; Prev[nedge]=info[x];info[x]=nedge; ed[nedge][0]=x;ed[nedge][1]=y;ed[nedge][2]=c;}voidSplit () {memset (dep,-1, sizeof (DEP)); L=0; Dep[q[r=1]=1]=0; father[1]=-1; while(L<r) {intX=Q[++L]; vis[x]=false; for(inty=info[x];y!=-1; Y=prev[y]) {if(dep[v[y]]==-1) {dep[q[++r]=v[y]]=dep[x]+1; Father[v[y]]=x; } } } for(inti=n;i;i--) {intx=q[i],p=-1; size[x]=1; for(inty=info[x];y!=-1; Y=prev[y]) {if(Vis[v[y]]) {Size[x]+=size[v[y]];if(p==-1|| SIZE[V[Y]]>SIZE[P]) p=v[y]; } }if(p==-1) {idx[x]=len[++cnt]=1; belong[head[cnt]=x]=cnt; }Else{Idx[x]=++len[belong[x]=belong[p]]; Head[belong[x]]=x; } vis[x]=true; }}voidGet_pos () {intPOS[MAXN]; pos[1]=0; for(intI=2; i<=cnt;i++) pos[i]=pos[i-1]+len[i-1]; for(intI=1; i<=n;i++) pos[i]=pos[belong[i]]+idx[i];}/****************** Segment Tree Section ****************************///Interval modified single point query you can also use a tree-like arrayintaddv[maxn*4];voidPush_down (intOintLintR) {if(L==R)return; addv[o<<1]+=addv[o]; addv[o<<1|1]+=addv[o]; addv[o]=0;}voidUpdateintOintLintRintLintRintVal) {if(L<=L&&R>=R) {addv[o]+=val; }Else{Push_down (o,l,r);intMid= (l+r) >>1;if(l<=mid) update (lson,l,r,val);if(r>mid) update (rson,l,r,val); }}intQuarry (intOintLintRintPOS) {if(L==R)returnAddv[o]; Push_down (O,L,R);intMid= (l+r) >>1;if(Pos>mid)returnQuarry (Rson,pos);Else returnQuarry (Lson,pos);}/****************** The edge of the tree after splitting the section ****************************/voidChangeintAintBintVal) {intFU=HEAD[BELONG[A]],FV=HEAD[BELONG[B]]; while(FU!=FV) {Update (1,1, N,pos[b],pos[fv],val); B=FATHER[FV]; FV=HEAD[BELONG[B]]; } Update (1,1, n,pos[b],pos[a],val);}/*****************bfs The multiplication relationship and the weights and ***************/to the root node edgevoidBFsintRoot) { for(intI=1; i<=nedge;i++) {if(dep[ed[i][0]]<dep[ed[i][1]])Continue; val[ed[i][0]]=ed[i][2]; } fa[root][0]=root; dep[root]=0; L=r=0; val[root]=0; Q[r++]=root; while(L<r) {intU=q[l++]; val[u]=val[u]+val[fa[u][0]]; for(intI=1; i<deg;i++) {fa[u][i]=fa[fa[u][i-1]][i-1]; } for(inti=info[u];i!=-1; I=prev[i]) {intDrc=v[i];if(Drc==father[u])Continue; dep[drc]=dep[u]+1; fa[drc][0]=u; Q[R++]=DRC; } }}/********************* the DFS sequence and its inverse function **************************/voidFdgintRoot) {inttt=0; Q[tt++]=root; rk[root]=0;intRr=0; while(tt>0){intU=Q[--TT]; rk[u]=rr++; for(inti=info[u];i!=-1; I=prev[i]) {intDrc=v[i];if(drc==fa[u][0])Continue; Q[TT++]=DRC; } } for(intI=1; i<=n;i++) {frk[rk[i]]=i; }}/******************* multiplication method to seek lca******************************/intLcaintAintb) {if(Dep[a]>dep[b]) swap (A, b);intHU=DEP[A],HV=DEP[B];intTu=a,tv=b; for(intI=0, tt=hv-hu;tt;i++,tt/=2){if(tt&1) Tv=fa[tv][i]; }if(TU==TV)returnTu for(inti=deg-1; ~i;i--) {if(Fa[tu][i]==fa[tv][i])Continue; Tu=fa[tu][i]; Tv=fa[tv][i]; }returnfa[tu][0];}/********************** The lca***********************/of the current collectionset<int> set;set<int>::iterator it;intGet_lca () {if(Set.empty ())return-1;if(set.size () = =1){returnFrk[*set.begin ()]; }Else{it=set.end (); it--;returnLCA (Frk[*set.begin ()],frk[*it]); }}/******************* multiplication method for critical node *************************/intGet_key_node (intu) {if(Quarry (1,1, N,pos[u]))returnU for(inti=deg-1; ~i;i--) {intTp=quarry (1,1, N,pos[fa[u][i]]);if(TP)Continue; U=fa[u][i]; }returnfa[u][0];}/**** Initialize ****/voidInit () {memset (ADDV,0, sizeof (ADDV)); Nedge=0; Set.clear (); Cnt=0; memset (info,-1, sizeof (info));}/********** Sub-situation processing inquiry ***************/voidSolveintAintb) {intLCA1,LCA2;intKey_node;if(a==1){if(Set.find (Rk[b]) ==set.end ()) {Lca1=get_lca (); Set.insert (Rk[b]); Lca2=get_lca ();if(lca1==-1) {Change (1B1); }Else{if(LCA2==LCA1) {Key_node=get_key_node (b); ans+= (Val[b]-val[key_node]); }Else{ans+= (val[b]+val[lca1]-2*VAL[LCA2]); } Change (1B1); } } }Else{if(Set.find (Rk[b])!=set.end ()) {Lca1=get_lca (); Set.erase (Rk[b]); Lca2=get_lca (); Change1, b,-1);if(lca2==-1){ }Else{if(LCA1==LCA2) {Key_node=get_key_node (b); ans-= (Val[b]-val[key_node]); }Else{ans-= (val[b]+val[lca2]-2*VAL[LCA1]); } } } }}intMain () {//Freopen ("100.in", "R", stdin);//Freopen ("Data.out", "w", stdout); intt,m,cas=0; scanf"%d", &t); while(t--) {init (); printf"Case #%d:\n", ++cas); scanf"%d%d", &n,&m);intA,b,c; for(intI=1; i<n;i++) {scanf ("%d%d%d", &a,&b,&c); Insert (A,B,C); Insert (B,A,C); } split (); Get_pos (); BFs1); Fdg1); cn1=0; while(m--) {scanf ("%d%d", &a,&b); Solve (A, b); printf"%d\n", ans); } }return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
HDU 5296 annoying problem tree chain analysis of LCA multiplication