[SDOI2014]旅行

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。

给每一个信仰建一颗线段树

因为内存不够,所以要动态建点

配合树链剖分对链修改查询就行了

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 struct Node
  8 {
  9   int next,to;
 10 }edge[200001];
 11 int head[100001],num,fa[100001],size[100001],son[100001],top[100001],dfn[100001],cnt,pos;
 12 int sum[5000001],Max[5000001],ch[5000001][2],dep[100001],root[100001],n,Q,w[100001],c[100001];
 13 void add(int u,int v)
 14 {
 15   num++;
 16   edge[num].next=head[u];
 17   head[u]=num;
 18   edge[num].to=v;
 19 }
 20 void dfs1(int x,int pa)
 21 {int i;
 22   fa[x]=pa;
 23   size[x]=1;
 24   dep[x]=dep[pa]+1;
 25   for (i=head[x];i;i=edge[i].next)
 26     {
 27       int v=edge[i].to;
 28       if (v!=pa)
 29     {
 30       dfs1(v,x);
 31       size[x]+=size[v];
 32       if (size[v]>size[son[x]]) son[x]=v;
 33     }
 34     }
 35 }
 36 void dfs2(int x,int pa,int tp)
 37 {int i;
 38   top[x]=tp;
 39   dfn[x]=++cnt;
 40   if (son[x])
 41     {
 42       dfs2(son[x],x,tp);
 43     }
 44   for (i=head[x];i;i=edge[i].next)
 45     {
 46       int v=edge[i].to;
 47       if (v==pa||v==son[x]) continue;
 48       dfs2(v,x,v);
 49     }
 50 }
 51 void update(int &rt,int l,int r,int x,int k)
 52 {
 53   if (!rt) rt=++pos;
 54   if (l==r)
 55     {
 56       sum[rt]+=k;
 57       Max[rt]=sum[rt];
 58       return;
 59     }
 60   int mid=(l+r)/2;
 61   if (x<=mid) update(ch[rt][0],l,mid,x,k);
 62   else update(ch[rt][1],mid+1,r,x,k);
 63   Max[rt]=max(Max[ch[rt][0]],Max[ch[rt][1]]);
 64   sum[rt]=sum[ch[rt][0]]+sum[ch[rt][1]];
 65 }
 66 int query(int rt,int l,int r,int L,int R,int ki)
 67 {
 68   if (!rt) return 0;
 69   if (l>=L&&r<=R)
 70     {
 71       if (ki==1) return sum[rt];
 72       else return Max[rt];
 73     }
 74   int mid=(l+r)/2,s;
 75   if (ki==1) s=0;
 76   else s=-2e9;
 77   if (L<=mid)
 78     {
 79       int x=query(ch[rt][0],l,mid,L,R,ki);
 80       if (ki==1) s+=x;
 81       else s=max(s,x);
 82     }
 83     if (R>mid)
 84     {
 85       int x=query(ch[rt][1],mid+1,r,L,R,ki);
 86       if (ki==1) s+=x;
 87       else s=max(s,x);
 88     }
 89     return s;
 90 }
 91 int ask1(int x,int y,int z)
 92 {
 93   int s=0;
 94   //cout<<"BILI"<<endl;
 95   while (top[x]!=top[y])
 96     {
 97       if (dep[top[x]]<dep[top[y]])swap(x,y);
 98       s+=query(root[z],1,n,dfn[top[x]],dfn[x],1);
 99       x=fa[top[x]];
100     }
101   if (dep[x]<dep[y]) swap(x,y);
102   s+=query(root[z],1,n,dfn[y],dfn[x],1);
103   return s;
104 }
105 int ask2(int x,int y,int z)
106 {
107   int s=-2e9;
108   //cout<<"VAN"<<endl;
109   while (top[x]!=top[y])
110     {
111       if (dep[top[x]]<dep[top[y]])swap(x,y);
112       s=max(s,query(root[z],1,n,dfn[top[x]],dfn[x],2));
113       x=fa[top[x]];
114     }
115   if (dep[x]<dep[y]) swap(x,y);
116   s=max(s,query(root[z],1,n,dfn[y],dfn[x],2));
117   return s;
118 }
119 int main()
120 {int i,u,v,x,y;
121   char s[11];
122   cin>>n>>Q;
123   for (i=1;i<=n;i++)
124     scanf("%d%d",&w[i],&c[i]);
125   for (i=1;i<=n-1;i++)
126     {
127       scanf("%d%d",&u,&v);
128       add(u,v);add(v,u);
129     }
130   dfs1(1,0);dfs2(1,0,1);
131   for (i=1;i<=n;i++)
132     update(root[c[i]],1,n,dfn[i],w[i]);
133   for (i=1;i<=Q;i++)
134     {
135       scanf("%s",s);
136       scanf("%d%d",&x,&y);
137       if (s[0]=='C'&&s[1]=='C')
138     {
139       update(root[c[x]],1,n,dfn[x],-w[x]);
140       update(root[y],1,n,dfn[x],w[x]);
141       c[x]=y;
142     }
143       else if (s[0]=='C'&&s[1]=='W')
144     {
145       update(root[c[x]],1,n,dfn[x],y-w[x]);
146       w[x]=y;
147     }
148       else if (s[0]=='Q'&&s[1]=='S')
149     {
150       printf("%d\n",ask1(x,y,c[x]));
151     }
152       else if (s[0]=='Q'&&s[1]=='M')
153     {
154       printf("%d\n",ask2(x,y,c[x]));
155     }
156     }
157 }

 

posted @ 2018-01-11 14:24  Z-Y-Y-S  阅读(221)  评论(0编辑  收藏  举报