bzoj 1036: [ZJOI2008]树的统计Count (树链剖分+线段树 点权)
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 21194 Solved: 8589
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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
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
1
2
2
10
6
5
6
5
16
ps:
这道题用cin输入会超时。用了提速的也没用。。
实现代码;
#include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int M = 1e5+10; vector<int>g[M]; int sum[M<<2],maxx[M<<2]; int cnt,n,q; int siz[M],son[M],fa[M],top[M],rk[M],tid[M],dep[M],a[M],cnt1,head[M]; struct node{int to,next;}e[M]; void add(int u,int v){ e[++cnt1].to = v;e[cnt1].next = head[u];head[u] = cnt1; e[++cnt1].to = u;e[cnt1].next = head[v];head[v] = cnt1; } void dfs1(int u,int faz,int deep){ dep[u] = deep; fa[u] = faz; siz[u] = 1; for(int i = head[u];i;i=e[i].next){ int v = e[i].to; if(v != fa[u]){ dfs1(v,u,deep+1); siz[u] += siz[v]; if(son[u] == -1||siz[v] > siz[son[u]]) son[u] = v; } } } void dfs2(int u,int t){ top[u] = t; tid[u] = cnt; rk[cnt] = u; cnt++; if(son[u] == -1) return; dfs2(son[u],t); for(int i = head[u];i;i = e[i].next){ int v = e[i].to; if(v != son[u]&&v != fa[u]) dfs2(v,v); } } void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; maxx[rt] = max(maxx[rt<<1|1],maxx[rt<<1]); } void update(int p,int c,int l,int r,int rt){ if(l == r){ sum[rt] = maxx[rt] = c; return ; } int m = (l + r) >> 1; if(p <= m) update(p,c,lson); else update(p,c,rson); pushup(rt); } int querys(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ return sum[rt]; } int m = (l + r) >> 1; int ret = 0; if(L <= m) ret += querys(L,R,lson); if(R > m) ret += querys(L,R,rson); return ret; } int querym(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ return maxx[rt]; } int m = (l + r) >> 1; int ret = -0x3f3f3f3f; if(L <= m) ret = max(ret,querym(L,R,lson)); if(R > m) ret = max(ret,querym(L,R,rson)); return ret; } int asks(int x,int y){ int sum = 0; int fx = top[x],fy = top[y]; while(fx != fy){ if(dep[fx] < dep[fy]){ swap(fx,fy); swap(x,y); } sum += querys(tid[fx],tid[x],1,n,1); x = fa[fx]; fx = top[x]; } if(dep[x] > dep[y]) swap(x,y); sum += querys(tid[x],tid[y],1,n,1); return sum; } int askm(int x,int y){ int ans = -0x3f3f3f3f; int fx = top[x],fy = top[y]; while(fx!=fy){ if(dep[fx] < dep[fy]){ swap(x,y);swap(fx,fy); } ans = max(ans,querym(tid[fx],tid[x],1,n,1)); x = fa[fx]; fx = top[x]; } if(dep[x] > dep[y]) swap(x,y); ans = max(ans,querym(tid[x],tid[y],1,n,1)); return ans; } int main() { int u,v,x,y; memset(son,-1,sizeof(son)); scanf("%d",&n); cnt = 1;cnt1= 1; for(int i = 0;i < n- 1;i ++){ scanf("%d%d",&u,&v); add(u,v); } for(int i = 1;i <= n;i ++) scanf("%d",&a[i]); dfs1(1,0,1); dfs2(1,1); for(int i = 1;i <= n; i++){ update(tid[i],a[i],1,n,1); } int q; char s[10]; scanf("%d",&q); while(q--){ scanf("%s",s); scanf("%d%d",&x,&y); if(s[1] == 'S') printf("%d\n",asks(x,y)); else if(s[1]=='M') printf("%d\n",askm(x,y)); else update(tid[x],y,1,n,1); } return 0; }