BZOJ 1036([ZJOI2008]树的统计Count-树链剖分[成熟版])
2013-07-07 12:54
501 查看
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3205 Solved: 1335
[Submit][Status]
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
41 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
41
2
2
10
6
5
6
5
16
在yzc的RP++模板下:
我完成了成熟版的树链剖分
本次更新的主要内容:
1.趋向于把值存在点上
2.引入了dfs序的概念
3.成功的只建一棵线段树,从此和可持久化说再见
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXN (30000+10) #define MAXM (200000+10) long long mul(long long a,long long b){return (a*b)%F;} long long add(long long a,long long b){return (a+b)%F;} long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} typedef long long ll; int n,m; ll sum[MAXN<<3]={0},maxv[MAXN<<3]={0}; void update(int x){sum[x]=sum[Lson]+sum[Rson],maxv[x]=max(maxv[Lson],maxv[Rson]);} void change(int x,int l,int r,int L,int c) { if (l==r) {sum[x]=maxv[x]=c;return;} int m=l+r>>1; if (L<=m) change(Lson,l,m,L,c); else change(Rson,m+1,r,L,c); update(x); } ll qurrysum(int x,int l,int r,int L,int R) { if (L<=l&&r<=R) return sum[x]; int m=l+r>>1; ll ans=0; if (L<=m) ans+=qurrysum(Lson,l,m,L,R); if (m<R) ans+=qurrysum(Rson,m+1,r,L,R); return ans; } ll qurrymax(int x,int l,int r,int L,int R) { if (L<=l&&r<=R) return maxv[x]; int m=l+r>>1; ll ans=-INF; if (L<=m) ans=max(ans,qurrymax(Lson,l,m,L,R)); if (m<R) ans=max(ans,qurrymax(Rson,m+1,r,L,R)); return ans; } int edge[MAXN*2],pre[MAXN]={0},next[MAXN*2]={0},size=0; void addedge(int u,int v) { edge[++size]=v; next[size]=pre[u]; pre[u]=size; } void addedge2(int u,int v){addedge(u,v),addedge(v,u);} int dep[MAXN]={0},siz[MAXN]={0},opt[MAXN]={0},father[MAXN]={0}; void dfs(int x) { siz[x]=1; dep[x]=dep[father[x]]+1; Forp(x) { int &v=edge[p]; if (v^father[x]) { father[v]=x; dfs(v); siz[x]+=siz[v]; if (siz[v]>siz[opt[x]]) opt[x]=v; } } } int top[MAXN],w[MAXN],place[MAXN],tim=0; void dfs2(int x,int chain) { top[x]=chain; place[x]=++tim; change(1,1,n,place[x],w[x]); if (opt[x]) dfs2(opt[x],chain);else return; Forp(x) { int &v=edge[p]; if (v^father[x]&&v^opt[x]) { dfs2(v,v); } } } ll lca_sum(int u,int v) { ll ans=0; while (top[u]^top[v]) { if (dep[top[u]]<dep[top[v]]) swap(u,v); ans+=qurrysum(1,1,n,place[top[u]],place[u]); u=father[top[u]]; } if (dep[u]<dep[v]) swap(u,v); ans+=qurrysum(1,1,n,place[v],place[u]); return ans; } ll lca_max(int u,int v) { ll ans=-INF; while (top[u]^top[v]) { if (dep[top[u]]<dep[top[v]]) swap(u,v); ans=max(ans,qurrymax(1,1,n,place[top[u]],place[u])); u=father[top[u]]; } if (dep[u]<dep[v]) swap(u,v); ans=max(ans,qurrymax(1,1,n,place[v],place[u])); return ans; } char c[10]; int main() { // freopen("bzoj1036.in","r",stdin); scanf("%d",&n); /* For(i,n) { int p,l,r,c; cin>>p>>l>>r; if (p==1) change(1,1,n,l,r); if (p==2) cout<<qurrysum(1,1,n,l,r)<<endl; if (p==3) cout<<qurrymax(1,1,n,l,r)<<endl; }*/ For(i,n-1) { int u,v; scanf("%d%d",&u,&v); addedge2(u,v); } For(i,n) scanf("%d",&w[i]); dfs(1); dfs2(1,1); scanf("%d",&m); For(i,m) { int a,b; scanf("%s%d%d",c,&a,&b); switch(c[1]) { case'H':change(1,1,n,place[a],b);break; case'S':printf("%lld\n",lca_sum(a,b));break; case'M':printf("%lld\n",lca_max(a,b)); } } return 0; }
相关文章推荐
- 树链剖分 - BZOJ 1036: [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)
- BZOJ[1036] [ZJOI2008]树的统计Count 树链剖分模板
- bzoj 1036 ZJOI2008 树的统计count (树链剖分
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)(线段树单点修改)
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- _bzoj1036 [ZJOI2008]树的统计Count【树链剖分】
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
- 文章标题 BZOJ 1036 : [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- 【树链剖分/线段树】BZOJ1036-[ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- bzoj 1036: [ZJOI2008]树的统计Count(树链剖分 点权)
- BZOJ1036:[ZJOI2008]树的统计Count 树链剖分 / LCT
- BZOJ-1036: [ZJOI2008]树的统计Count (树链剖分 线段树 单点修改 区间查询 入门题)
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
- bzoj1036: [ZJOI2008]树的统计Count 树链剖分
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)
- 树链剖分基础模板(BZOJ1036[ZJOI2008]树的统计Count)