Bzoj3531: [Sdoi2014]旅行
Submit: 1698 Solved: 758
Description
S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。
Input
输入的第一行包含整数N,Q依次表示城市数和事件数。
接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
接下来N-1行每行两个整数x,y表示一条双向道路。
接下来Q行,每行一个操作,格式如上所述。
Output
对每个QS和QM事件,输出一行,表示旅行者记下的数字。
Sample Input
3 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4
Sample Output
9
11
3
HINT
N,Q < =10^5 , C < =10^5
数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时
刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。
Source
树链剖分+线段树森林
时间限制还是很良心的
不考虑颜色问题的话,这就是个树点权求改,链权求和的树剖裸题。
加上颜色问题的话……看到题目的时间限制和空间限制,似乎可以放心搞事情。
建C棵线段树,每棵线段树维护一种颜色的结点信息,每次在对应颜色的线段树上统计答案。
如果用root*2 root*2+1的写法存子树,空间妥妥炸,那么改成指针式就好。由于操作数的限制,实际上每棵线段树最终只会建出来一小部分。
极限状况下线段树最多需要添加log(10^5)/log(2) * n == 160w个结点
1 #include<algorithm> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdio> 5 using namespace std; 6 const int mxn=100010; 7 int read(){ 8 int x=0,f=1;char ch=getchar(); 9 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 11 return x*f; 12 } 13 struct edge{int v,nxt;}e[mxn<<1]; 14 int hd[mxn],mct=0; 15 void add_edge(int u,int v){e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;} 16 int n,Q; 17 struct node{ 18 int top,fa; 19 int w,e; 20 int size,son; 21 }t[mxn]; 22 int dep[mxn]; 23 struct sgt{ 24 int lc,rc; 25 int mx,smm; 26 }st[mxn<<4]; 27 int sz=0;//sct=0; 28 int rt[mxn]; 29 int w[mxn],c[mxn]; 30 void DFS1(int u,int fa){ 31 t[u].fa=fa; 32 t[u].size=1; 33 dep[u]=dep[fa]+1; 34 for(int i=hd[u];i;i=e[i].nxt){ 35 int v=e[i].v; 36 if(v==fa)continue; 37 DFS1(v,u); 38 t[u].size+=t[v].size; 39 if(t[v].size>t[t[u].son].size) 40 t[u].son=v; 41 } 42 return; 43 } 44 void DFS2(int u,int top){ 45 t[u].w=++sz; 46 t[u].top=top; 47 if(t[u].son)DFS2(t[u].son,top); 48 for(int i=hd[u];i;i=e[i].nxt){ 49 int v=e[i].v; 50 if(v!=t[u].son && v!=t[u].fa)DFS2(v,v); 51 } 52 t[u].e=sz; 53 return; 54 } 55 void pushup(int rt){ 56 int lc=st[rt].lc;int rc=st[rt].rc; 57 st[rt].mx=max(st[lc].mx,st[rc].mx); 58 st[rt].smm=st[lc].smm+st[rc].smm; 59 return; 60 } 61 void update(int p,int v,int l,int r,int &rt){ 62 if(!rt){rt=++sz;} 63 if(l==r){st[rt].mx=st[rt].smm=v;return;} 64 int mid=(l+r)>>1; 65 if(p<=mid)update(p,v,l,mid,st[rt].lc); 66 else update(p,v,mid+1,r,st[rt].rc); 67 pushup(rt); 68 return; 69 } 70 int qsum(int L,int R,int l,int r,int rt){ 71 // printf("%d %d %d %d %d :%d\n",L,R,l,r,rt,st[rt].smm); 72 if(!rt)return 0; 73 if(L<=l && r<=R){return st[rt].smm;} 74 int mid=(l+r)>>1; 75 int res=0; 76 if(L<=mid)res+=qsum(L,R,l,mid,st[rt].lc); 77 if(R>mid)res+=qsum(L,R,mid+1,r,st[rt].rc); 78 return res; 79 } 80 int qmax(int L,int R,int l,int r,int rt){ 81 if(!rt)return -1e9; 82 if(L<=l && r<=R){return st[rt].mx;} 83 int mid=(l+r)>>1; 84 int res=-1e9; 85 if(L<=mid)res=max(res,qmax(L,R,l,mid,st[rt].lc)); 86 if(R>mid)res=max(res,qmax(L,R,mid+1,r,st[rt].rc)); 87 return res; 88 } 89 int asksum(int color,int x,int y){ 90 int res=0; 91 while(t[x].top!=t[y].top){ 92 if(dep[t[x].top]<dep[t[y].top])swap(x,y); 93 res+=qsum(t[t[x].top].w,t[x].w,1,n,rt[color]); 94 x=t[t[x].top].fa; 95 } 96 if(dep[x]>dep[y])swap(x,y); 97 res+=qsum(t[x].w,t[y].w,1,n,rt[color]); 98 return res; 99 } 100 int askmax(int color,int x,int y){ 101 int res=-1e9; 102 while(t[x].top!=t[y].top){ 103 if(dep[t[x].top]<dep[t[y].top])swap(x,y); 104 res=max(res,qmax(t[t[x].top].w,t[x].w,1,n,rt[color])); 105 x=t[t[x].top].fa; 106 } 107 if(dep[x]>dep[y])swap(x,y); 108 res=max(res,qmax(t[x].w,t[y].w,1,n,rt[color])); 109 return res; 110 } 111 int main() 112 { 113 int i,j,u,v; 114 n=read();Q=read(); 115 for(i=1;i<=n;i++){w[i]=read();c[i]=read();} 116 for(i=1;i<n;i++){ 117 u=read();v=read(); 118 add_edge(u,v); 119 add_edge(v,u); 120 } 121 DFS1(n/2,0); 122 DFS2(n/2,n/2); 123 for(i=1;i<=n;i++){ 124 update(t[i].w,w[i],1,n,rt[c[i]]); 125 } 126 char op[5];int x,y; 127 while(Q--){ 128 scanf("%s",op);x=read();y=read(); 129 if(op[0]=='C'){ 130 if(op[1]=='C'){ 131 update(t[x].w,0,1,n,rt[c[x]]); 132 c[x]=y; 133 update(t[x].w,w[x],1,n,rt[c[x]]); 134 } 135 else{ 136 update(t[x].w,y,1,n,rt[c[x]]); 137 w[x]=y; 138 } 139 } 140 else{ 141 if(op[1]=='S'){ 142 printf("%d\n",asksum(c[x],x,y)); 143 } 144 else{ 145 printf("%d\n",askmax(c[x],x,y)); 146 } 147 } 148 } 149 return 0; 150 }