【SPOJ-QTREE3】树链剖分
http://www.spoj.com/problems/QTREE3/
时间限制:2s 代码长度限制:50000B 内存限制:1536MB
【题目描述】
给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白
有两种操作:
0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)
1 v : 询问1到v的路径上的第一个黑点,若无,输出-1
总共有12组数据。
1/3 的数据, N=5000, Q=400000.
1/3 的数据, N=10000, Q=300000.
1/3 的数据,N=100000, Q=100000.
【输入格式】
单组数据的。
第一行 N and Q.表示N个点和Q个操作
下来N-1条无向边
下来 Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).
【输出格式】
遇到 "1 v"操作的时候,输出结果。
这题就是树链剖分,线段树维护当前区间最左边的黑点的编号。因为是单点修改,所以根本不用lazy,也不用记录点的颜色(看它所维护的最左边的点这个值是否为0)。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 const int N=1000100; 8 struct trnode{ 9 int lc,rc,l,r,c,d,lazy; 10 }t[2*N]; 11 struct node{ 12 int x,y,next; 13 }a[2*N]; 14 int n,m,tl,z,len; 15 int first[N],tot[N],son[N],fa[N],dep[N],ys[N],yss[N],top[N]; 16 17 void ins(int x,int y) 18 { 19 len++; 20 a[len].x=x;a[len].y=y; 21 a[len].next=first[x];first[x]=len; 22 } 23 24 int maxx(int x,int y){return x>y ? x:y;} 25 int minn(int x,int y){return x<y ? x:y;} 26 27 int build_tree(int l,int r) 28 { 29 int x=++tl; 30 t[x].l=l;t[x].r=r; 31 t[x].c=t[x].d=t[x].lazy=0; 32 t[x].lc=t[x].rc=0; 33 if(l<r) 34 { 35 int mid=(l+r)>>1; 36 t[x].lc=build_tree(l,mid); 37 t[x].rc=build_tree(mid+1,r); 38 } 39 return x; 40 } 41 42 void change(int x,int p) 43 { 44 int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1; 45 if(t[x].l==t[x].r) 46 { 47 if(t[x].d==0) t[x].d=t[x].l; 48 else t[x].d=0; 49 return; 50 } 51 if(p<=mid) change(lc,p); 52 else change(rc,p); 53 if(t[lc].d) t[x].d=t[lc].d; 54 else if(t[rc].d) t[x].d=t[rc].d; 55 else t[x].d=0; 56 } 57 58 int query(int x,int l,int r) 59 { 60 if(t[x].l==l && t[x].r==r) return t[x].d; 61 int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1; 62 if(r<=mid) return query(lc,l,r); 63 else if(l>mid) return query(rc,l,r); 64 else 65 { 66 int t1=query(lc,l,mid); 67 if(t1) return t1; 68 int t2=query(rc,mid+1,r); 69 if(t2) return t2; 70 return 0; 71 } 72 } 73 74 void dfs1(int x) 75 { 76 tot[x]=1;son[x]=0; 77 for(int i=first[x];i;i=a[i].next) 78 { 79 int y=a[i].y; 80 if(y==fa[x]) continue; 81 fa[y]=x; 82 dep[y]=dep[x]+1; 83 dfs1(y); 84 if(tot[son[x]]<tot[y]) son[x]=y; 85 tot[x]+=tot[y]; 86 } 87 } 88 89 void dfs2(int x,int tp) 90 { 91 ys[x]=++z;yss[z]=x;top[x]=tp; 92 if(son[x]) dfs2(son[x],tp); 93 for(int i=first[x];i;i=a[i].next) 94 { 95 int y=a[i].y; 96 if(y==fa[x] || y==son[x]) continue; 97 dfs2(y,y); 98 } 99 } 100 101 int solve(int y) 102 { 103 int ty=top[y],ans=-1; 104 while(ty!=1) 105 { 106 int t=query(1,ys[ty],ys[y]); 107 if(t) ans=yss[t]; 108 y=fa[ty];ty=top[y]; 109 } 110 int t; 111 if(y==1) t=query(1,1,1); 112 else t=query(1,1,ys[y]); 113 if(t) ans=yss[t]; 114 return ans; 115 } 116 117 int main() 118 { 119 freopen("a.in","r",stdin); 120 // freopen("me.out","w",stdout); 121 scanf("%d%d",&n,&m); 122 tl=0;len=0;z=0; 123 memset(first,0,sizeof(first)); 124 for(int i=1;i<n;i++) 125 { 126 int x,y; 127 scanf("%d%d",&x,&y); 128 ins(x,y),ins(y,x); 129 } 130 build_tree(1,n); 131 fa[1]=0;dep[1]=1;dfs1(1); 132 dfs2(1,1); 133 for(int i=1;i<=m;i++) 134 { 135 int tmp,x; 136 scanf("%d%d",&tmp,&x); 137 if(!tmp) change(1,ys[x]); 138 else 139 { 140 int ans=solve(x); 141 if(ans) printf("%d\n",ans); 142 else printf("-1\n"); 143 } 144 } 145 return 0; 146 }