BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
2017-02-27 16:55
375 查看
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 15446 Solved: 6283
[Submit][Status][Discuss]
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
这是一个赤果果的树链剖分题。
支持路径修改查询。
看代码吧
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<iomanip> using namespace std; const int N=30005; int n,q; int deep ,fa ,pos ,v ,size ,top ; int head ,cnt,sz; struct data { int nt,to; }edge[4*N]; struct seg { int l,r,mx,sum; }t[4*N]; inline void add(int u,int v) { edge[++cnt]=(data){head[u],v};head[u]=cnt; edge[++cnt]=(data){head[v],u};head[v]=cnt; } inline int read() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=10*x+ch-'0';ch=getchar();} return x*f; } void initial() { n=read(); int x,y; for(int i=1;i<n;i++) { x=read();y=read(); add(x,y); } for(int i=1;i<=n;i++) v[i]=read(); } inline void dfs1(int u) { int v; size[u]=1; for(int i=head[u];i;i=edge[i].nt) { v=edge[i].to; if(v==fa[u])continue; fa[v]=u; deep[v]=deep[u]+1; dfs1(v); size[u]+=size[v]; } } inline void dfs2(int x,int tp) { int k=0,v;sz++; pos[x]=sz;top[x]=tp; for(int i=head[x];i;i=edge[i].nt) { v=edge[i].to; if(v==fa[x])continue; if(size[v]>size[k])k=v; } if(k==0)return ; dfs2(k,tp); for(int i=head[x];i;i=edge[i].nt) { v=edge[i].to; if(v==fa[x])continue; if(v!=k) dfs2(v,v); } } inline void build(int k,int l,int r) { t[k].l=l,t[k].r=r; if(l==r)return ; int mid=(r+l)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } inline void modify(int k,int x,int y) { int l=t[k].l,r=t[k].r; if(l==r){t[k].mx=t[k].sum=y;return ;} int mid=(l+r)>>1; if(mid<x)modify(k<<1|1,x,y); else modify(k<<1,x,y); t[k].sum=t[k<<1].sum+t[k<<1|1].sum; t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx); } inline int query_sum(int k,int x,int y) { int l=t[k].l,r=t[k].r,mid=(r+l)>>1; if(r<=y&&l>=x){return t[k].sum;} if(mid<x){return query_sum(k<<1|1,x,y);} else if(mid>=y){return query_sum(k<<1,x,y);} else return query_sum(k<<1|1,x,y)+query_sum(k<<1,x,y); } inline int query_max(int k,int x,int y) { int l=t[k].l,r=t[k].r,mid=(r+l)>>1; //cout<<t[k].mx<<endl; if(l>=x&&r<=y)return t[k].mx; if(mid<x)return query_max(k<<1|1,x,y); else if(mid>=y)return query_max(k<<1,x,y); else return max(query_max(k<<1|1,x,y),query_max(k<<1,x,y)); } inline int solve_sum(int x,int y) { int sum=0; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])swap(x,y); sum+=query_sum(1,pos[top[x]],pos[x]); x=fa[top[x]]; } if(pos[x]>pos[y])swap(x,y); sum+=query_sum(1,pos[x],pos[y]); return sum; } inline int solve_max(int x,int y) { int maxn=-0X3f3f3f3f; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])swap(x,y); maxn=max(maxn,query_max(1,pos[top[x]],pos[x])); x=fa[top[x]]; } if(pos[x]>pos[y])swap(x,y); maxn=max(maxn,query_max(1,pos[x],pos[y])); return maxn; } void solve() { int x,y; char ch[10]; q=read(); build(1,1,n); for(int i=1;i<=n;i++)modify(1,pos[i],v[i]); for(int i=1;i<=q;i++) { scanf("%s",ch); x=read();y=read(); if(ch[0]=='C'){v[x]=y;modify(1,pos[x],y);} else { if(ch[1]=='M') printf("%d\n",solve_max(x,y)); else printf("%d\n",solve_sum(x,y)); } } } int main() { initial(); dfs1(1); dfs2(1,1); solve(); return 0; }
相关文章推荐
- 树链剖分+线段树 BZOJ 1036 [ZJOI2008]树的统计Count
- 【块状树】【树链剖分】bzoj1036 [ZJOI2008]树的统计Count
- 【树链剖分模板】【bzoj1036】: [ZJOI2008]树的统计Count
- BZOJ 树链剖分 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [zjoi 2008] 数的统计 (树链剖分)
- bzoj1036[ZJOI2008]树的统计Count
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
- BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】
- [BZOJ 1036] ZJOI 2008 树的统计Count · 树链剖分
- BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】
- 【BZOJ 1036】【ZJOI 2008】树的统计 树链剖分模板题
- [ZJOI2008] [BZOJ1036] 树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )
- BZOJ 1036 [ZJOI2008] 树的统计Count
- bzoj1036: [ZJOI2008]树的统计Count - 树链剖分
- bzoj 1036 [ZJOI2008]树的统计Count 树链剖分
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分裸题)
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- bzoj1036 [ZJOI2008]树的统计(树链剖分/lct)
- [BZOJ1036][JZOJ2256]【ZJOI2008】树的统计(树链剖分模板)