BZOJ 3531 SDOI2014 旅行 树链剖分+线段树动态开点
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531
题意概述:
给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作:
1.将点x的颜色改成c。
2.将点x的权值给成w。
3.询问x->y路径上和端点相同颜色的点的权值总和(端点颜色相同)。
4.询问x->y路径上和端点相同颜色的点的权值最大值(端点颜色相同)。
分析:
首先树链剖分,每条链开C棵维护每个颜色的线段树。动态开点。
感觉没什么好说的......考试的时候灵光一闪就来了......之前还在YYlct之类的......
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<cctype> 12 using namespace std; 13 const int maxn=100005; 14 const int SIZE=4000005; 15 16 int N,Q,C[maxn],W[maxn]; 17 map<int,int>rt[maxn]; 18 struct edge{ int to,next; }E[maxn<<1]; 19 int first[maxn],np,dep[maxn],top[maxn],fa[maxn],son[maxn],sz[maxn],len[maxn]; 20 int lc[SIZE],rc[SIZE],sum[SIZE],mx[SIZE],np2; 21 22 void _scanf(int &x) 23 { 24 x=0; 25 char ch=getchar(); 26 while(ch<'0'||ch>'9') ch=getchar(); 27 while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); 28 } 29 void _scanf(char *s) 30 { 31 int cnt=0; 32 char ch=getchar(); 33 while(!isalpha(ch)) ch=getchar(); 34 while(isalpha(ch)) s[cnt++]=ch,ch=getchar(); 35 s[cnt]='\0'; 36 } 37 int out_cnt,out[15]; 38 void _printf(int x) 39 { 40 out[++out_cnt]=x%10,x/=10; 41 while(x) out[++out_cnt]=x%10,x/=10; 42 while(out_cnt) putchar('0'+out[out_cnt--]); 43 putchar('\n'); 44 } 45 void add_edge(int u,int v){ 46 E[++np]=(edge){v,first[u]}; 47 first[u]=np; 48 } 49 void data_in() 50 { 51 _scanf(N);_scanf(Q); 52 for(int i=1;i<=N;i++) _scanf(W[i]),_scanf(C[i]); 53 int x,y; 54 for(int i=1;i<N;i++){ 55 _scanf(x);_scanf(y); 56 add_edge(x,y); add_edge(y,x); 57 } 58 } 59 void DFS1(int i,int f,int d){ 60 fa[i]=f,dep[i]=d,sz[i]=1; 61 for(int p=first[i];p;p=E[p].next){ 62 int j=E[p].to; 63 if(j==f) continue; 64 DFS1(j,i,d+1); 65 sz[i]+=sz[j]; 66 if(sz[j]>sz[son[i]]) son[i]=j; 67 } 68 } 69 void DFS2(int i,int f,int tp){ 70 top[i]=tp,len[tp]++; 71 if(son[i]) DFS2(son[i],i,tp); 72 for(int p=first[i];p;p=E[p].next){ 73 int j=E[p].to; 74 if(j==f||j==son[i]) continue; 75 DFS2(j,i,j); 76 } 77 } 78 int newnode(){ 79 np2++,lc[np2]=rc[np2]=0,sum[np2]=mx[np2]=0; 80 return np2; 81 } 82 void pushup(int now){ 83 mx[now]=max(mx[lc[now]],mx[rc[now]]); 84 sum[now]=sum[lc[now]]+sum[rc[now]]; 85 } 86 void update(int &now,int L,int R,int pos,int v){ 87 if(!now) now=newnode(); 88 if(L==R){ sum[now]=mx[now]=v; return; } 89 int m=L+R>>1; 90 if(pos<=m) update(lc[now],L,m,pos,v); 91 else update(rc[now],m+1,R,pos,v); 92 pushup(now); 93 } 94 void build(int i,int f){ 95 update(rt[top[i]][C[i]],0,len[top[i]]-1,dep[i]-dep[top[i]],W[i]); 96 for(int p=first[i];p;p=E[p].next){ 97 if(E[p].to==f) continue; 98 build(E[p].to,i); 99 } 100 } 101 int query1(int now,int L,int R,int A,int B){ 102 if(!now) return 0; 103 if(A<=L&&R<=B) return sum[now]; 104 int m=L+R>>1; 105 if(B<=m) return query1(lc[now],L,m,A,B); 106 if(A>m) return query1(rc[now],m+1,R,A,B); 107 return query1(lc[now],L,m,A,B)+query1(rc[now],m+1,R,A,B); 108 } 109 int query2(int now,int L,int R,int A,int B){ 110 if(!now) return 0; 111 if(A<=L&&R<=B) return mx[now]; 112 int m=L+R>>1; 113 if(B<=m) return query2(lc[now],L,m,A,B); 114 if(A>m) return query2(rc[now],m+1,R,A,B); 115 return max(query2(lc[now],L,m,A,B),query2(rc[now],m+1,R,A,B)); 116 } 117 int LCA(int x,int y){ 118 while(top[x]!=top[y]){ 119 if(dep[top[x]]<dep[top[y]]) swap(x,y); 120 x=fa[top[x]]; 121 } 122 return dep[x]<dep[y]?x:y; 123 } 124 int query_s(int x,int y,int c){ 125 int re=0; 126 while(top[x]!=top[y]){ 127 re+=query1(rt[top[x]][c],0,len[top[x]]-1,0,dep[x]-dep[top[x]]); 128 x=fa[top[x]]; 129 } 130 re+=query1(rt[top[x]][c],0,len[top[x]]-1,dep[y]-dep[top[x]],dep[x]-dep[top[x]]); 131 return re; 132 } 133 int query_m(int x,int y,int c){ 134 int re=0; 135 while(top[x]!=top[y]){ 136 re=max(re,query2(rt[top[x]][c],0,len[top[x]]-1,0,dep[x]-dep[top[x]])); 137 x=fa[top[x]]; 138 } 139 re=max(re,query2(rt[top[x]][c],0,len[top[x]]-1,dep[y]-dep[top[x]],dep[x]-dep[top[x]])); 140 return re; 141 } 142 void work() 143 { 144 DFS1(1,0,1); 145 DFS2(1,0,1); 146 build(1,0); 147 char op[5]; 148 int x,y,z,p,c,w,ans; 149 for(int i=1;i<=Q;i++){ 150 _scanf(op); 151 if(op[0]=='C'&&op[1]=='C'){ 152 _scanf(x);_scanf(c); 153 update(rt[top[x]][C[x]],0,len[top[x]]-1,dep[x]-dep[top[x]],0); 154 update(rt[top[x]][C[x]=c],0,len[top[x]]-1,dep[x]-dep[top[x]],W[x]); 155 } 156 else if(op[0]=='C'&&op[1]=='W'){ 157 _scanf(x);_scanf(w); 158 update(rt[top[x]][C[x]],0,len[top[x]]-1,dep[x]-dep[top[x]],W[x]=w); 159 } 160 else if(op[1]=='S'){ 161 _scanf(x);_scanf(y); 162 z=LCA(x,y); 163 _printf(query_s(x,z,C[x])+query_s(y,z,C[x])-(C[z]==C[x]?W[z]:0)); 164 } 165 else if(op[1]=='M'){ 166 _scanf(x);_scanf(y); 167 z=LCA(x,y); 168 _printf(max(query_m(x,z,C[x]),query_m(y,z,C[x]))); 169 } 170 } 171 } 172 int main() 173 { 174 data_in(); 175 work(); 176 return 0; 177 }