1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MB Submit: 13024 Solved: 5253
Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input 输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output 对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
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
树链剖分裸题,用线段树维护。。。
#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(1,1); } 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); return max(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; }