1036: Count of [ZJOI2008] trees
Time Limit:10 Sec Memory limit:162 MB
submit:13024 solved:5253
Description
There are n nodes on a tree, numbered 1 to N, each with a weight of W. We will ask you to do something about this tree in the following form: I. Change u t: Changing the weight of the node U to t ii. QMAX U V: asks for the maximum weight of the node on the path from point u to v. Qsum u V: ask for the weights of nodes on the path from point U to V and note that nodes on the path from point u to v include U and V itself
Input
The first behavior of the input is an integer n, which represents the number of nodes. The next n–1 line, with 2 integers a and b per line, indicates that there is an edge connected between Node A and Node B. Next n rows, one integer per line, and the integer of line I, WI represents the weight of node I. The next 1 lines, an integer q, represent the total number of operations. The next Q line, one operation per line, is given in the form "Change U T" or "QMAX u V" or "Qsum u V".
For 100% data, ensure that the weight of each node in the 1<=n<=30000,0<=q<=200000; midway operation is between 30000 and 30000.
Output
For each "QMAX" or "qsum" operation, each line outputs an integer representing the result of the required output.
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
Qsum 3 4
Qsum 2 1
Change 1 5
QMAX 3 4
Change 3 6
QMAX 3 4
QMAX 2 4
Qsum 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
Tree chain split bare topic, maintenance with line tree ...
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath > #include <vector> #include <queue> #include <stack> #include <map> #include <set> #
include<string> #include <iomanip> #include <ctime> #include <climits> #include <cctype>
#include <algorithm> #ifdef WIN32 #define AUTO "%i64d" #else #define AUTO "%lld" #endif using namespace std; #define SMAX (X,TMP) X=max (x), (TMP) #define SMIN (x,tmp) X=min ((x), (TMP)) #define MAXX (X1,X2,X3) Max (Max (X1,X2), x3) #
Define MINN (x1,x2,x3) min (min (x1,x2), x3) const int inf=0x3f3f3f3f;
const int MAXN = 30005; struct Edge {int to,next;}
edge[maxn<<1];
int HEAD[MAXN];
int Maxedge;
inline void Addedge (int u,int v) {Edge[++maxedge] = (edge) {V,head[u]};
Head[u] = Maxedge;
Edge[++maxedge] = (Edge) {u,head[v]};
HEAD[V] = Maxedge;
} int A[MAXN],ID[MAXN],RID[MAXN],TOP[MAXN]; int Depth[maxn],son[maxn],size[maxn],fa[maXN]; int sum[maxn<<2],mx[maxn<<2];
SEG part int Maxnode;
int n;
void dfs1 (int u,int father,int deep) {fa[u]=father; depth[u]=deep; size[u]=1;
for (int i=head[u];~i;i=edge[i].next) {int v = edge[i].to;
if (v = = father) Continue;
DFS1 (v,u,deep+1);
Size[u] + = Size[v];
if (!son[u] | | size[v]>size[son[u]]) son[u]=v;
}} void dfs2 (int u,int tp) {top[u]=tp; id[u]=++maxnode; rid[maxnode]=u;
if (Son[u]) DFS2 (SON[U],TP);
for (int i=head[u];~i;i=edge[i].next) {int v = edge[i].to;
if (V==fa[u] | | v==son[u]) continue;
DFS2 (V,V);
}} void Init () {scanf ("%d", &n);
memset (head,-1,sizeof (head));
Maxedge =-1;
for (int i=1;i<n;i++) {int x, y;
scanf ("%d%d", &x,&y);
Addedge (x, y);
} for (int i=1;i<=n;i++) scanf ("%d", a+i);
memset (son,0,sizeof (son));
memset (size,0,sizeof (size));
memset (depth,0,sizeof (depth)); MemSet (Top,0,sizeof (top));
DFS1 (1,-1,1);
DFS2 (a);
} inline void update (int root) {sum[root]=sum[root<<1]+sum[root<<1|1];
Mx[root]=max (mx[root<<1],mx[root<<1|1]);
} void Build (int root,int l,int R) {if (l==r) {sum[root]=mx[root]=a[rid[l]];
Return
} int m= (L+R) >>1;
Build (ROOT<<1,L,M);
Build (Root<<1|1,m+1,r);
Update (root);
} void Modify (int root,int l,int r,int pos,int val) {if (l==r) {sum[root]=mx[root]=val;
return;
} int m= (L+R) >>1;
if (pos<=m) modify (Root<<1,l,m,pos,val);
else modify (Root<<1|1,m+1,r,pos,val);
Update (root);
} int querysum (int root,int l,int r,int x,int y) {if (x<=l && r<=y) return sum[root];
int m= (L+R) >>1;
int ret=0;
if (x<=m && l<=y) ret + = Querysum (root<<1,l,m,x,y);
if (y>=m+1 && r>=x) ret + = Querysum (root<<1|1,m+1,r,x,y); return ret;
} int Querymax (int root,int l,int r,int x,int y) {if (x<=l && r<=y) return mx[root];
int m= (L+R) >>1;
int ret=-inf;
if (x<=m && l<=y) Smax (ret, Querymax (root<<1,l,m,x,y));
if (y>=m+1 && r>=x) Smax (ret, Querymax (root<<1|1,m+1,r,x,y));
return ret;
} int findsum (int u,int v) {int ret=0;
int T1=TOP[U],T2=TOP[V];
while (T1^T2) {if (Depth[t1]<depth[t2]) swap (T1,T2), swap (U,V);
RET + = Querysum (1,1,maxnode,id[t1],id[u]);
U=FA[T1];
T1=top[u];
} if (Depth[u]<depth[v]) swap (U,V);
RET + = Querysum (1,1,maxnode,id[v],id[u]);
return ret;
} int Findmax (int u,int v) {int ret=-inf;
int T1=TOP[U],T2=TOP[V];
while (T1^T2) {if (Depth[t1]<depth[t2]) swap (T1,T2), swap (U,V);
Smax (Ret,querymax (1,1,maxnode,id[t1],id[u));
U=FA[T1];
T1=top[u];
} if (Depth[u]<depth[v]) swap (U,V); ReturnMax (Ret,querymax (1,1,maxnode,id[v],id[u));
} void Work () {build (1,1,maxnode);
int q;
scanf ("%d", &q);
int x, y;
Char s[10];
while (q--) {scanf ("%s%d%d", s,&x,&y);
if (s[0]== ' C ') modify (1,1,maxnode,id[x],y);
else if (s[1]== ' s ') printf ("%d\n", Findsum (x, y));
else printf ("%d\n", Findmax (x, y));
}} int main () {freopen ("count.in", "R", stdin);
Freopen ("Count.out", "w", stdout);
Init ();
Work ();
return 0;
}