SPOJ 2939. Query on a tree VProblem code: QTREE5 |
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N. We define dist(a, b) as the number of edges on the path from node a to node b.
Each node has a color, white or black. All the nodes are black initially.
We will ask you to perfrom some instructions of the following form:
For each "1 v" operation, print one integer representing its result. If there is no white node in the tree, you should write "-1".
Input: 10 1 2 1 3 2 4 1 5 1 6 4 7 7 8 5 9 1 10 10 0 6 0 6 0 6 1 3 0 1 0 1 1 3 1 10 1 4 1 6 Output: 2 2 2 3 0
--------------------------------------------------
题目大意:一颗树,边上权值都是1,一开始树上的节点都是黑色。有两种操作:0操作是将某个节点黑色变白色,白色变黑色;1操作是询问某个节点距离最近的白色节点的距离
解题思路:跟QTREE4很像,使用树链剖分+堆维护,有了QTREE4的基础,这题就迎刃而解了。自此,QTREE系列就做完了。
#include <stdio.h> #include <string.h> #include <vector> #include <queue> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; const int N=100005,M=N*7,inf=0x7fffffff; struct Node{ int v,p; bool operator<(const Node & a)const{ return v>a.v; } Node(int a,int c):v(a),p(c){} }; int n,cnum,pnum; vector<int>gra[N]; int son[N],fa[N],top[N],siz[N],white[N]; int cp[N],cd[N],csz[N],pn[N],cid[M]; int maxl[M],maxr[M],le[M],ri[M]; priority_queue<Node>que[N]; void dfs_1(int s,int f){ fa[s]=f;top[s]=s;siz[s]=1; int maxx=0,p=-1,len=gra[s].size(); for(int i=0;i<len;i++){ int e=gra[s][i];if(e==f)continue; dfs_1(e,s);siz[s]+=siz[e]; if(siz[e]>maxx){maxx=siz[e];p=e;} }son[s]=p; } void build(int p,int rt,int l,int r){ int root=rt+p; le[root]=l;ri[root]=r; maxl[root]=maxr[root]=-1; int mid=(l+r)>>1; if(l==r)return ; build(p,rt<<1,l,mid); build(p,rt<<1|1,mid+1,r); } void update(int p,int rt,int x){ int root=rt+p,lroot=p+(rt<<1),rroot=p+(rt<<1|1); int l=le[root],r=ri[root],mid=(l+r)>>1; if(l==x&&r==x){ int s=cid[p+x],minn=-1; while(!que[s].empty()){ int v=que[s].top().v; int pp=que[s].top().p; if(maxl[pp]+1!=v){que[s].pop();continue;} minn=v;break; } if(white[s])maxl[root]=maxr[root]=0; else maxl[root]=maxr[root]=minn; if(rt==1&&~maxl[root]){ int f=fa[s]; if(~f)que[f].push(Node(maxl[root]+1,root)); } return ; } if(x<=mid)update(p,rt<<1,x); else update(p,rt<<1|1,x); maxl[root]=maxr[root]=-1; if(~maxl[lroot]&&(maxl[root]==-1||maxl[root]>maxl[lroot]))maxl[root]=maxl[lroot]; if(~maxl[rroot]&&(maxl[root]==-1||maxl[root]>maxl[rroot]+mid-l+1))maxl[root]=maxl[rroot]+mid-l+1; if(~maxr[rroot]&&(maxr[root]==-1||maxr[root]>maxr[rroot]))maxr[root]=maxr[rroot]; if(~maxr[lroot]&&(maxr[root]==-1||maxr[root]>maxr[lroot]+r-mid))maxr[root]=maxr[lroot]+r-mid; int s=cid[p+1]; if(rt==1&&~maxl[root]){ int f=fa[s]; if(~f)que[f].push(Node(maxl[root]+1,root)); } } int queryl(int p,int rt,int l,int r){ int root=p+rt; int mid=(le[root]+ri[root])>>1; if(l==le[root]&&r==ri[root]) return maxl[root]; if(r<=mid)return queryl(p,rt<<1,l,r); else if(l>mid)return queryl(p,rt<<1|1,l,r); else{ int ans=-1; int ret=queryl(p,rt<<1,l,mid); if(~ret&&(ans==-1||ans>ret))ans=ret; ret=queryl(p,rt<<1|1,mid+1,r); if(~ret&&(ans==-1||ans>ret+mid-l+1))ans=ret+mid-l+1; return ans; } } int queryr(int p,int rt,int l,int r){ int root=p+rt; int mid=(le[root]+ri[root])>>1; if(l==le[root]&&r==ri[root]) return maxr[root]; if(r<=mid)return queryr(p,rt<<1,l,r); else if(l>mid)return queryr(p,rt<<1|1,l,r); else{ int ans=-1; int ret=queryr(p,rt<<1,l,mid); if(~ret&&(ans==-1||ans>ret+r-mid))ans=ret+r-mid; ret=queryr(p,rt<<1|1,mid+1,r); if(~ret&&(ans==-1||ans>ret))ans=ret; return ans; } } void dfs_2(int s,int d){ if(s==top[s]){ cp[s]=++cnum;csz[cnum]=0;pn[cnum]=pnum; } while(!que[s].empty())que[s].pop(); cp[s]=cp[top[s]];cd[s]=d;int k=cp[s]; csz[k]=d;cid[d+pn[k]]=s; if(~son[s]){ top[son[s]]=top[s];dfs_2(son[s],d+1); } int len=gra[s].size(); for(int i=0;i<len;i++){ int e=gra[s][i]; if(e!=fa[s]&&e!=son[s])dfs_2(e,1); } if(son[s]==-1){ pnum+=6*d;build(pn[k],1,1,d); } } int main(){ // freopen("/home/axorb/in","r",stdin); // freopen("/home/axorb/out","w",stdout); scanf("%d",&n);clr(white,0); for(int i=1;i<=n;i++)gra[i].clear(); for(int i=1;i<n;i++){ int a,b;scanf("%d%d",&a,&b); gra[a].push_back(b);gra[b].push_back(a); } cnum=pnum=0;dfs_1(1,-1);dfs_2(1,1); int q;scanf("%d",&q); while(q--){ int a,b;scanf("%d%d",&a,&b); if(a==0){ white[b]^=1; while(~b){ update(pn[cp[b]],1,cd[b]); b=fa[top[b]]; } } else{ int minn=-1,tmp=0; while(~b){ int ll=queryl(pn[cp[b]],1,cd[b],csz[cp[b]]); int rr=queryr(pn[cp[b]],1,1,cd[b]); if(ll!=-1&&(minn==-1||minn>ll+tmp))minn=ll+tmp; if(rr!=-1&&(minn==-1||minn>rr+tmp))minn=rr+tmp; tmp+=cd[b];b=fa[top[b]]; } printf("%d\n",minn); } } }