【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
来源:互联网 发布:阿尔法家家具软件 编辑:程序博客网 时间:2024/04/25 23:22
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
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
题解:树链剖分模板题。。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,q,sz,cnt,m;struct use{ int st,en;}b[100001];struct zff{ int maxx,sum;}tree[1000001];int fa[100001][15],size[1000001],deep[100001],point[100001],next[1000001],vis[1000001],pos[1000001],w[1000001],aa,bb;int belong[1000001],ffpos[1000001];char ch[10001];void add(int x,int y){ next[++cnt]=point[x];point[x]=cnt; b[cnt].st=x;b[cnt].en=y; }void init(){ int a,b; scanf("%d",&n); for (int i=1;i<=n-1;i++) { scanf("%d%d",&a,&b); add(a,b);add(b,a); } for (int i=1;i<=n;i++) scanf("%d",&w[i]);}void build(int x,int l,int r){ int mid; if (l==r){tree[x].maxx=w[ffpos[l]];tree[x].sum=w[ffpos[l]];return;} mid=(l+r)/2; build(x*2,l,mid); build(x*2+1,mid+1,r); tree[x].maxx=max(tree[x*2].maxx,tree[x*2+1].maxx); tree[x].sum=tree[x*2].sum+tree[x*2+1].sum; }void dfs(int x){ size[x]=1;vis[x]=1; for (int i=1;i<=14;i++) { if (deep[x]<(1<<i)) break; fa[x][i]=fa[fa[x][i-1]][i-1]; } for (int i=point[x];i;i=next[i]) { if (vis[b[i].en]==1) continue; deep[b[i].en]=deep[x]+1; fa[b[i].en][0]=x; dfs(b[i].en); size[x]+=size[b[i].en]; }}void dfs2(int x,int c){ int k(0); pos[x]=++sz; ffpos[sz]=x; belong[x]=c; for (int i=point[x];i;i=next[i]) if (size[b[i].en]>size[k]&&deep[b[i].en]>deep[x]) k=b[i].en; if (k==0) return; dfs2(k,c); for (int i=point[x];i;i=next[i]) if (deep[b[i].en]>deep[x]&&b[i].en!=k) dfs2(b[i].en,b[i].en);}int lca(int x,int y){ int t; if(deep[x]<deep[y]) swap(x,y);t=deep[x]-deep[y]; for (int i=0;i<=14;i++) if (t&(1<<i)) x=fa[x][i]; for (int i=14;i>=0;i--) if (fa[x][i]!=fa[y][i]) {x=fa[x][i];y=fa[y][i];} if (x==y) return x;else return fa[x][0];}void insert(int k,int l,int r){ int mid; if(l==r&&l==pos[aa]){tree[k].maxx=w[aa];tree[k].sum=w[aa];return;} mid=(l+r)/2; if (pos[aa]<=mid) insert(k*2,l,mid); else insert(k*2+1,mid+1,r); tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx); tree[k].sum=tree[2*k].sum+tree[2*k+1].sum; }int qsum(int k,int l,int r,int xx,int yy){ int mid,zsum=0; if (xx<=l&&r<=yy) return tree[k].sum; mid=(l+r)/2; if (xx<=mid) zsum+=qsum(k*2,l,mid,xx,yy); if (yy>mid) zsum+=qsum(k*2+1,mid+1,r,xx,yy); return zsum;}int qmax(int k,int l,int r,int xx,int yy){ int mid,zmax=-999999999; if (xx<=l&&r<=yy) { return tree[k].maxx; } mid=(l+r)/2; if (xx<=mid) zmax=max(zmax,qmax(k*2,l,mid,xx,yy)); if (yy>mid) zmax=max(zmax,qmax(k*2+1,mid+1,r,xx,yy)); return zmax; }int ssum(int x,int y){ int zsum(0); while (belong[x]!=belong[y]) { zsum+=qsum(1,1,n,pos[belong[x]],pos[x]); x=fa[belong[x]][0]; } zsum+=qsum(1,1,n,pos[y],pos[x]); return zsum; } int smax(int x,int y){ int zmax(-999999999); while (belong[x]!=belong[y]) { zmax=max(zmax,qmax(1,1,n,pos[belong[x]],pos[x])); x=fa[belong[x]][0]; } zmax=max(zmax,qmax(1,1,n,pos[y],pos[x])); return zmax;}void solve(){ int t; build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s%d%d",ch,&aa,&bb); if (ch[0]=='C'){w[aa]=bb;insert(1,1,n);} else { t=lca(aa,bb); if (ch[1]=='M') printf("%d\n",max(smax(aa,t),smax(bb,t))); else printf("%d\n",ssum(aa,t)+ssum(bb,t)-w[t]); } }} int main(){ init(); dfs(1); dfs2(1,1); solve();}
0 0
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- 【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
- BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
- bzoj1036: [ZJOI2008]树的统计Count - 树链剖分
- 【树链剖分】[BZOJ1036][ZJOI2008]树的统计Count
- [树链剖分] BZOJ1036: [ZJOI2008]树的统计Count
- [bzoj1036][ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】 [ZJOI2008]树的统计Count
- [Bzoj1036][ZJOI2008]树的统计Count
- 【BZOJ1036】【ZJOI2008】树的统计Count 树链剖分裸题
- 【ZJOI2008】【BZOJ1036】树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count && LCT
- bzoj1036: [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count
- bzoj1036: [ZJOI2008]树的统计Count
- BZOJ1036: [ZJOI2008]树的统计Count
- Ubuntu下redis安装并设置开机自启动
- 每日一题(8)——二进制中1的个数
- Terra 轨道
- REST介绍
- 修复android 5.0 Xutils的框架问题retry error, curr request is null
- 【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
- svn使用说明
- 集合类及泛型
- iOS基础篇之——helloword工程搭建及基本数据类型简介
- CentOS-6.3安装配置Apache2.2.6
- Intent回传数据与Activity生命周期
- ZOJ 2297 Survival 【状态压缩】
- 每日一题(11)——单链表常见问题
- Websphere liberty cluster installation