Bzoj3531: [Sdoi2014]旅行

Posted SilverNebula

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj3531: [Sdoi2014]旅行相关的知识,希望对你有一定的参考价值。

Time Limit: 20 Sec  Memory Limit: 512 MB
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

5 6
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

8
9
11
3

HINT

 

N,Q < =10^5    , C < =10^5


 数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时

刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

 

Source

Round 1 Day 1

 

树链剖分+线段树森林

时间限制还是很良心的

不考虑颜色问题的话,这就是个树点权求改,链权求和的树剖裸题。

加上颜色问题的话……看到题目的时间限制和空间限制,似乎可以放心搞事情。

建C棵线段树,每棵线段树维护一种颜色的结点信息,每次在对应颜色的线段树上统计答案。

如果用root*2 root*2+1的写法存子树,空间妥妥炸,那么改成指针式就好。由于操作数的限制,实际上每棵线段树最终只会建出来一小部分。

  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 }

 

 

 

以上是关于Bzoj3531: [Sdoi2014]旅行的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3531: [Sdoi2014]旅行

BZOJ3531SDOI2014旅行

bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

Bzoj3531: [Sdoi2014]旅行

[BZOJ]3531: [Sdoi2014]旅行

BZOJ 3531SDOI 2014旅行 树链剖分