【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 }

 

posted @ 2016-08-08 11:29  拦路雨偏似雪花  阅读(784)  评论(0编辑  收藏  举报