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 }
View Code

 

 
posted @ 2018-03-25 15:33  KKKorange  阅读(203)  评论(0编辑  收藏  举报