SPOJ Problem Set (classical)2666. Query on a tree IVProblem code: QTREE4 |
You are given a tree (an acyclic undirected connected graph) with N nodes, and nodes numbered 1,2,3...,N. Each edge has an integer value assigned to it(note that the value can be negative). Each node has a color, white or black. We define dist(a, b) as the sum of the value of the edges on the path from node a to node b.
All the nodes are white initially.
We will ask you to perfrom some instructions of the following form:
For each "A" operation, write one integer representing its result. If there is no white node in the tree, you should write "They have disappeared.".
Input: 3 1 2 1 1 3 1 7 A C 1 A C 2 A C 3 A Output: 2 2 0 They have disappeared.
--------------------------------------------------------
题目大意:见漆子超论文。
解题思路:见漆子超论文。吐槽吐槽,我写了两天的代码,都怪自己代码能力太弱,看懂了论文,知道了过程,无奈写不出来。
/* 题目来源:SPOJ2666. Query on a tree IV 题目难度:难题+神题 解题思路:树链剖分+线段树维护 漆子超论文里面的原题,思路完全从那里看过来的,无奈树链剖分以及线段树的维护太过于 繁琐,编码复杂,写了两天。因为这道题的树链剖分实际上是应用了树的链的分治,对于每 条重链都要建立一颗线段树,那么重链的个数在极限情况下有O(n)个,都不可能对每个线段 树开单独的数组来维护,考虑到所有线段树的节点之和其实不会超过6*N个,我就开了一个 储存线段树的数组,对于每个不同的线段树,我设置一个漂移量pn[t],那么t这个线段树的 根节点在数组中的实际位置是pn[t]+1,另外还有很多奇怪的序号需要维护:son[i]代表i 的重链儿子所在的边,fa[i]代表i节点的父亲节点所在的边,top[i]表示i所在的重链的链头, siz[i]表示i的子孙节点的数量,cp[i]表示i所在的重链的编号,cd[i]表示i在自己重链上 的第几个位置,csz[i]表示编号为i的重链的节点数量,pn[i]表示编号为i的重链的漂移量, cid[i]表示它所在的重链t上第(i-pn[t])上的点在树中的编号,cnum重链计数,pnum漂移 量计数。 代码极其丑陋,可以排进我的十大最丑陋代码了 */ #include <stdio.h> #include <string.h> #include <queue> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; const int N=200005,M=7*N,inf=0x7fffffff; struct Node{ int v,p; bool operator<(const Node & a)const{ return v<a.v; } Node(int a,int b):v(a),p(b){} }; int n,eid; int head[N],ed[N<<1],val[N<<1],nxt[N<<1]; int son[N],fa[N],top[N],siz[N],dis[N],col[N]; int cp[N],cd[N],csz[N],pn[N],cid[M],cnum,pnum; int le[M],ri[M],maxl[M],maxr[M],opt[M]; priority_queue<Node>que[N],allque; void addedge(int s,int e,int v){ ed[eid]=e;val[eid]=v;nxt[eid]=head[s];head[s]=eid++; } int pl(int a,int b){ if(a==-inf||b==-inf)return -inf; return a+b; } void dfs_1(int s,int f){ siz[s]=1;int maxx=0,p=-1;top[s]=s;fa[s]=f; for(int i=head[s];~i;i=nxt[i]){ int e=ed[i];if(e==f){fa[s]=i;continue;} dfs_1(e,s);siz[s]+=siz[e]; if(siz[e]>maxx){maxx=siz[e];p=i;} } son[s]=p; } void buildtree(int p,int rt,int l,int r){ le[p+rt]=l;ri[p+rt]=r;int mid=(l+r)>>1; maxl[p+rt]=maxr[p+rt]=opt[p+rt]=-inf; if(l==r)return ; buildtree(p,rt<<1,l,mid); buildtree(p,rt<<1|1,mid+1,r); } void update(int p,int rt,int x){ int l=le[p+rt],r=ri[p+rt],mid=(l+r)>>1; int root=p+rt,lroot=p+(rt<<1),rroot=p+(rt<<1|1); if(l==x&&r==x){ int s=cid[p+x],d1=-inf,d2=-inf,p1=-1; while(!que[s].empty()){ int v=que[s].top().v,ps=que[s].top().p;que[s].pop(); int e=cid[ps]; if(maxl[ps]+val[fa[e]]!=v)continue; p1=ps;d1=v;break; } while(!que[s].empty()){ int v=que[s].top().v,ps=que[s].top().p,e=cid[ps]; if(maxl[ps]+val[fa[e]]!=v||ps==p1){que[s].pop();continue;} d2=v;break; } if(~p1)que[s].push(Node(d1,p1)); if(col[s])maxl[root]=maxr[root]=max(d1,0); else maxl[root]=maxr[root]=d1; if(col[s])opt[root]=max(d1,pl(d1,d2)); else opt[root]=pl(d1,d2); if(col[s])opt[root]=max(opt[root],0); if(rt==1){ if(~fa[s]){ int f=ed[fa[s]],v=val[fa[s]]; if(maxl[root]!=-inf)que[f].push(Node(maxl[root]+v,root)); } if(opt[root]!=-inf)allque.push(Node(opt[root],root)); } return ; } if(x<=mid)update(p,rt<<1,x); else update(p,rt<<1|1,x); int dm0=dis[cid[p+mid]],dm1=dis[cid[p+mid+1]]; int dr=dis[cid[p+r]],dl=dis[cid[p+l]]; maxl[root]=max(maxl[lroot],pl(dm1-dl,maxl[rroot])); maxr[root]=max(maxr[rroot],pl(dr-dm0,maxr[lroot])); opt[root]=max(opt[lroot],opt[rroot]); opt[root]=max(opt[root],pl(pl(maxl[rroot],maxr[lroot]),dm1-dm0)); int s=cid[p+1]; if(rt==1){ if(~fa[s]){ int f=ed[fa[s]],v=val[fa[s]]; if(maxl[root]!=-inf)que[f].push(Node(maxl[root]+v,root)); } if(opt[root]!=-inf)allque.push(Node(opt[root],root)); } } void dfs_2(int s,int d,int c){ if(s==top[s]){cp[s]=++cnum;csz[cp[s]]=0;} if(~son[s]){ top[ed[son[s]]]=top[s];dfs_2(ed[son[s]],d+val[son[s]],c+1); } for(int i=head[s];~i;i=nxt[i]) if(i!=son[s]&&i!=fa[s])dfs_2(ed[i],0,1); cp[s]=cp[top[s]];cd[s]=c;int k=cp[s]; csz[k]=max(csz[k],cd[s]);dis[s]=d; if(s==top[s]){ pn[k]=pnum;pnum+=6*csz[k]; int t=s,num=2;cid[pn[k]+1]=s; while(~son[t]){ cid[pn[k]+num]=ed[son[t]]; t=ed[son[t]];num++; } } } void dfsinit(int s){ col[s]=1; if(~son[s])dfsinit(ed[son[s]]); for(int i=head[s];~i;i=nxt[i]) if(i!=fa[s]&&i!=son[s])dfsinit(ed[i]); update(pn[cp[s]],1,cd[s]); } int main(){ // freopen("/home/axorb/in","r",stdin); // freopen("/home/axorb/out","w",stdout); scanf("%d",&n);eid=0;clr(head,-1); for(int i=1;i<n;i++){ int a,b,c;scanf("%d%d%d",&a,&b,&c); addedge(a,b,c);addedge(b,a,c); } dfs_1(1,-1);cnum=pnum=0;dfs_2(1,0,1);clr(col,0); while(!allque.empty())allque.pop(); for(int i=1;i<=cnum;i++){ while(!que[i].empty())que[i].pop();buildtree(pn[i],1,1,csz[i]); } dfsinit(1); // printf("%d\n",allque.top().v); int q;scanf("%d",&q); while(q--){ char ss[20];scanf("%s",ss); if(ss[0]=='A'){ int flag=0; while(!allque.empty()){ int v=allque.top().v,p=allque.top().p; if(opt[p]!=v){allque.pop();continue;} printf("%d\n",v);flag=1;break; } if(!flag)puts("They have disappeared."); } else{ int x;scanf("%d",&x);col[x]^=1; while(top[x]!=1){ update(pn[cp[x]],1,cd[x]);x=ed[fa[top[x]]]; } update(pn[cp[x]],1,cd[x]); } } }