3531. [SDOI2014] Travel [Tree Chain Segmentation]

Description

 S has N cities, numbered from 1 to N. The cities are connected by N-1 two-way roads, so that
all other cities can be reached from one city. Each city believes in different religions, such as flying noodle religion, invisible unicorn religion, and Jedi religion are all common beliefs. For convenience, we use different positive integers to represent various religions, and the residents of country S often travel. They always took the shortest route when traveling, and to avoid trouble, they only stayed in cities of the same faith as theirs. Of course, the end of the journey is also the city of the same faith as him. The government of S country has set a different travel rating for each city, and travelers often write down the sum or maximum rating of the cities they have stayed in on the way (including the origin and destination).
    In the history of country S, the following events often occurred:
"CC xc": all residents of city x converted to c religion;
"CW xw": the rating of city x was adjusted to w;
"QS xy": a traveler A traveler starts from city x, goes to city y, and records the sum of the ratings of the cities where he stayed on the way;
"QM xy": A traveler starts from city x, goes to city y, and records the cities where he stays on the way
. rating maximum.
    The numbers recorded by travelers have been lost due to age, but the beliefs and ratings of each city before the records began, as well as the event records themselves, are intact. Based on this information, restore the numbers the traveler wrote down. For convenience, we consider the intervals between events to be long enough that the ratings and beliefs of all cities remain the same on any given trip.

Input

    The first line of input contains the integer N, and Q represents the number of cities and then the number of events.
    Next N lines, the i+lth line, two integers Wi, Ci, in turn, represent the
rating and belief of city i before the recording starts.
    The next N-1 lines each have two integers x, y representing a two-way road.
    The next Q lines, one operation per line, are formatted as described above.

Output

    For each QS and QM event, output a row representing the number recorded by the traveler.

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

The data guarantees that for all QS and QM events, the starting and ending cities have the same belief; at any time
, the city's rating is always a positive integer no greater than 10^4, and the religion value is no greater than C.

 

Because the board was copied from another question, the details were not changed. It took WA twice to pass QAQ.
For this question, our first reaction was: Hey, this is not a bare tree chain division...

Wait, it doesn't seem quite right for
this person who only counts the same kind of people on the chain and the starting point and the end point every time. In
that case, we can do a chain dissection for each kind...

Wait, it seems that it is still not quite right to
open the space. QAQ
, then let's open the line segment tree dynamically.
Analysis of a wave of complexity: Only the update function in my code needs to be dynamically opened. In the worst case of each update, log nodes will be added in the worst case . In
that case, the space is NlogN.
get it

 

 

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define N (2000000+100)
  5 using namespace std;
  6 
  7 struct segt{int val,add,max,ls,rs;}Segt[N<<2],refun[N];
  8 struct node{int to,next;}edge[N<<1];
  9 int n,m,a[N],u,v,l,ans,w[N],c[N],Root[N],x,y;
 10 int head[N],num_edge;
 11 int Father[N],Depth[N],Son[N],Sum[N];
 12 int T_num[N],Tree[N],Top[N],dfs_num,segt_num;
 13 char opt[5];
 14 
 15 void add(int u,int v)
 16 {
 17     edge[++num_edge].to=v;
 18     edge[num_edge].next=head[u];
 19     head[u]=num_edge;
 20 }
 21 
 22 void Dfs1(int x) 
 23 {
 24     Sum[x]=1;
 25     Depth[x]=Depth[Father[x]]+1;
 26     for (int i=head[x]; i; i=edge[i].next)
 27         if (edge[i].to!=Father[x])
 28         {
 29             Father[edge[i].to]=x;
 30             Dfs1(edge[i].to);
 31             Sum[x]+=Sum[edge[i].to];
 32             if (!Son[x] || Sum[Son[x]]<Sum[edge[i].to])
 33                 Son[x]=edge[i].to;
 34         }
 35 }
 36 
 37 void Dfs2(int x,int pre)
 38 {
 39     T_num[x]=++dfs_num;
 40     Tree[dfs_num]=a[x];
 41     Top[x]=pre;
 42     if (Son[x]) Dfs2(Son[x],pre);
 43     for (int i=head[x]; i; i=edge[i].next)
 44         if (edge[i].to!=Father[x] && edge[i].to!=Son[x])
 45             Dfs2(edge[i].to,edge[i].to);
 46 }
 47 
 48 void Pushup(int now)
 49 {
 50     Segt[now].val=Segt[Segt[now].ls].val+Segt[Segt[now].rs].val;
 51     Segt[now].max=max(Segt[Segt[now].ls].max,Segt[Segt[now].rs].max);
 52 }
 53 
 54 void Update(int &now,int l,int r,int x,int k) 
 55 {
 56     if (!now) now=++segt_num;
 57     if (l==r)
 58     {
 59         Segt[now].val=k;
 60         Segt[now].max=k;
 61         return;
 62     }
 63     int mid=(l+r)>>1;
 64     if (x<=mid) Update(Segt[now].ls,l,mid,x,k);
 65     else Update(Segt[now].rs,mid+1,r,x,k);
 66     Pushup(now);
 67 }
 68 
 69 int Query_Sum(int now,int l,int r,int l1,int r1)
 70 {
 71     if (now==0) return 0;
 72     if (l>r1 || r<l1) return 0;
 73     if (l1<=l && r<=r1)
 74         return Segt[now].val;
 75     int mid=(l+r)>>1;
 76     if (r1<=mid) return Query_Sum(Segt[now].ls,l,mid,l1,r1);
 77     if (l1>=mid+1) return Query_Sum(Segt[now].rs,mid+1,r,l1,r1);
 78     return Query_Sum(Segt[now].ls,l,mid,l1,r1)+Query_Sum(Segt[now].rs,mid+1,r,l1,r1);
 79 }
 80 
 81 int Query_Max(int now,int l,int r,int l1,int r1)
 82 {
 83     if (now==0) return -1;
 84     if (l>r1 || r<l1) return -1;
 85     if (l1<=l && r<=r1)
 86         return Segt[now].max;
 87     int mid=(l+r)>>1;
 88     if (r1<=mid) return Query_Max(Segt[now].ls,l,mid,l1,r1);
 89     if (l1>=mid+1) return Query_Max(Segt[now].rs,mid+1,r,l1,r1);
 90     return max(Query_Max(Segt[now].ls,l,mid,l1,r1),Query_Max(Segt[now].rs,mid+1,r,l1,r1));
 91 }
 92 
 93 int Ask_Sum(int x,int y)
 94 {
 95     int fx=Top[x],fy=Top[y],r=c[x],ans=0;
 96     while (fx!=fy)
 97     {
 98         if (Depth[fx]<Depth[fy])
 99             swap(x,y),swap(fx,fy);
100         ans+=Query_Sum(Root[r],1,n,T_num[fx],T_num[x]);
101         x=Father[fx],fx=Top[x];
102     }
103     if (Depth[x]<Depth[y]) swap(x,y);
104     ans+=Query_Sum(Root[r],1,n,T_num[y],T_num[x]);
105     return ans; 
106 }
107 
108 int Ask_Max(int x,int y)
109 {
110     int fx=Top[x],fy=Top[y],r=c[x],ans=0;
111     while (fx!=fy)
112     {
113         if (Depth[fx]<Depth[fy])
114             swap(x,y),swap(fx,fy);
115         ans=max(ans,Query_Max(Root[r],1,n,T_num[fx],T_num[x]));
116         x=Father[fx],fx=Top[x];
117     }
118     if (Depth[x]<Depth[y]) swap(x,y);
119     ans=max(ans,Query_Max(Root[r],1,n,T_num[y],T_num[x]));
120     return ans; 
121 }
122 
123 int main()
124 {
125     scanf("%d%d",&n,&m);
126     for (int i=1; i<=n; ++i)
127         scanf("%d%d",&w[i],&c[i]);
128     for (int i=1; i<=n-1; ++i)
129     {
130         scanf("%d%d",&u,&v);
131         add(u,v); add(v,u);
132     }
133     Dfs1(1); Dfs2(1,1);
134     for (int i=1; i<=n; ++i)
135         Update(Root[c[i]],1,n,T_num[i],w[i]);
136         
137     for (int i=1; i<=m; ++i)
138     {
139         scanf("%s%d%d",opt,&x,&y);
140         if (opt[0]=='C' && opt[1]=='C')
141         {
142             Update(Root[c[x]],1,n,T_num[x],0);
143             c[x]=y;
144             Update(Root[c[x]],1,n,T_num[x],w[x]);
145         }
146         if (opt[0]=='C' && opt[1]=='W')
147         {
148             w[x]=y;
149             Update(Root[c[x]],1,n,T_num[x],w[x]);
150         }
151         if (opt[0]=='Q' && opt[1]=='S')
152             printf("%d\n",Ask_Sum(x,y));
153         if (opt[0]=='Q' && opt[1]=='M')
154             printf("%d\n",Ask_Max(x,y));
155     }        
156 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325294197&siteId=291194637