【树链剖分模板】【bzoj1036】: [ZJOI2008]树的统计Count
来源:互联网 发布:c语言联合体初始化为0 编辑:程序博客网 时间:2024/04/29 07:09
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5522 Solved: 2307
[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
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
HINT
Source
树的分治
裸链剖,好久没写了,熟悉一下
第一个代码没写LCA,第二个代码加了LCA
时间差距不大,没有必要就不用写
//#define _TEST _TEST#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>using namespace std;/////////////////////////////////////////////////#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)#define MS(arr,x) memset(arr,x,sizeof(arr))#define LL long long#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)/////////////////////////////////////////////////const int MAXN=30010;int n,q;struct edge{int v,next;}e[MAXN * 2];int head[MAXN];int k=0;int w[MAXN];int fa[MAXN];int son[MAXN];int dep[MAXN];int sz[MAXN];int top[MAXN];int fc[MAXN];int cnt;int mmax[70000];int dis[70000];/////////////////////////////////////////////////void adde(int u,int v){e[k].v=v;e[k].next=head[u];head[u]=k++;}void dfs1(int u,int distance){ son[u]=0; sz[u]=1; dis[u]=distance; INE(i,u,e) { int v=e[i].v; if(v==fa[u]) continue; fa[v]=u; dep[v]=dep[u]+1; dfs1(v,distance+w[v]); sz[u]+=sz[v]; if(sz[son[u]]<sz[v]) son[u]=v; }}void dfs2(int u,int tp){ top[u]=tp; fc[u]=++cnt; if(son[u]) dfs2(son[u],tp); INE(i,u,e) { int v=e[i].v; if(v==son[u] || v==fa[u]) continue; dfs2(v,v); }}void build(int id,int l,int r){ mmax[id]=-99999; if(l==r)return; int mid=(l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r);}int query1(int id,int l,int r,int L,int R){ if(l<=L && R<=r) return mmax[id]; int mid=(L+R)>>1; if(r<=mid) return query1(id<<1,l,r,L,mid); else if(l>mid) return query1(id<<1|1,l,r,mid+1,R); else return max(query1(id<<1,l,mid,L,mid),query1(id<<1|1,mid+1,r,mid+1,R));}int query2(int id,int l,int r,int L,int R){ if(l<=L && R<=r) return dis[id]; int mid=(L+R)>>1; if(r<=mid) return query2(id<<1,l,r,L,mid); else if(l>mid) return query2(id<<1|1,l,r,mid+1,R); else return query2(id<<1,l,mid,L,mid)+query2(id<<1|1,mid+1,r,mid+1,R);}void modify(int id,int pos,int x,int L,int R){ if(L==R) { mmax[id]=x; dis[id]=x; return; } int mid=(L+R)>>1; if(pos<=mid) modify(id<<1,pos,x,L,mid); else modify(id<<1|1,pos,x,mid+1,R); mmax[id]=max(mmax[id<<1],mmax[id<<1|1]); dis[id]=dis[id<<1]+dis[id<<1|1];}/*int LCA(int a,int b){ int ta=top[a],tb=top[b]; while(ta!=tb) { if(dep[ta]<dep[tb]) swap(a,b),swap(ta,tb); a=fa[ta]; ta=top[a]; } if(dep[a]<dep[b]) return a; else return b;}*/int getmax(int a,int b){ int ta=top[a],tb=top[b]; int ans=w[a]; while(ta!=tb) { if(dep[ta]<dep[tb]) swap(a,b),swap(ta,tb); ans=max(ans,query1(1,fc[ta],fc[a],1,cnt)); a=fa[ta]; ta=top[a]; } if(dep[a]>dep[b]) swap(a,b); return max(ans,query1(1,fc[a],fc[b],1,cnt));}int getdis(int a,int b){ int ta=top[a],tb=top[b]; int ans=0; while(ta!=tb) { if(dep[ta]<dep[tb])swap(a,b),swap(ta,tb); ans+=query2(1,fc[ta],fc[a],1,cnt); a=fa[ta]; ta=top[a]; } if(dep[a]>dep[b])swap(a,b); return ans+query2(1,fc[a],fc[b],1,cnt);}/////////////////////////////////////////////////void input(){ MS(head,-1); scanf("%d",&n); int u,v; rep(i,1,n-1) { scanf("%d%d",&u,&v); adde(u,v); adde(v,u); } rep(i,1,n) scanf("%d",&w[i]); scanf("%d",&q);}void solve(){ ///////////////////init/////////////////// char op[10]; int u,v; ////////////////calculate//////////////// // init HLT dfs1(1,w[1]); dfs2(1,1); build(1,1,n); rep(i,1,n) modify(1,fc[i],w[i],1,n); /*rep(i,1,n) printf("%d\n",query(1,fc[i],fc[i],1,cnt)); return;*/ // query while(q--) { scanf("%s%d%d",op,&u,&v); if(op[0]=='C')//CHANGE { w[u]=v; modify(1,fc[u],v,1,n); } else { if(op[1]=='M') //QMAX printf("%d\n",getmax(u,v)); else ///QSUM printf("%d\n",getdis(u,v)); } } /////////////////output///////////////// }/////////////////////////////////////////////////int main(){ #ifndef _TEST freopen("1036.in","r",stdin); freopen("1036.out","w",stdout); #endif input(); solve(); #ifdef _TEST for(;;); #endif return 0;}
//#define _TEST _TEST#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>using namespace std;/////////////////////////////////////////////////#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)#define MS(arr,x) memset(arr,x,sizeof(arr))#define LL long long#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)/////////////////////////////////////////////////const int MAXN=30010;int n,q;struct edge{int v,next;}e[MAXN * 2];int head[MAXN];int k=0;int w[MAXN];int fa[MAXN];int son[MAXN];int dep[MAXN];int sz[MAXN];int top[MAXN];int fc[MAXN];int cnt;int mmax[70000];int dis[70000];/////////////////////////////////////////////////void adde(int u,int v){e[k].v=v;e[k].next=head[u];head[u]=k++;}void dfs1(int u,int distance){ son[u]=0; sz[u]=1; dis[u]=distance; INE(i,u,e) { int v=e[i].v; if(v==fa[u]) continue; fa[v]=u; dep[v]=dep[u]+1; dfs1(v,distance+w[v]); sz[u]+=sz[v]; if(sz[son[u]]<sz[v]) son[u]=v; }}void dfs2(int u,int tp){ top[u]=tp; fc[u]=++cnt; if(son[u]) dfs2(son[u],tp); INE(i,u,e) { int v=e[i].v; if(v==son[u] || v==fa[u]) continue; dfs2(v,v); }}void build(int id,int l,int r){ mmax[id]=-99999; if(l==r)return; int mid=(l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r);}int query1(int id,int l,int r,int L,int R){ if(l<=L && R<=r) { return mmax[id]; } int mid=(L+R)>>1; if(r<=mid) return query1(id<<1,l,r,L,mid); else if(l>mid) return query1(id<<1|1,l,r,mid+1,R); else return max(query1(id<<1,l,mid,L,mid),query1(id<<1|1,mid+1,r,mid+1,R));}int query2(int id,int l,int r,int L,int R){ if(l<=L && R<=r) { return dis[id]; } int mid=(L+R)>>1; if(r<=mid) return query2(id<<1,l,r,L,mid); else if(l>mid) return query2(id<<1|1,l,r,mid+1,R); else return query2(id<<1,l,mid,L,mid)+query2(id<<1|1,mid+1,r,mid+1,R);}void modify(int id,int pos,int x,int L,int R){ if(L==R) { mmax[id]=x; dis[id]=x; return; } int mid=(L+R)>>1; if(pos<=mid) modify(id<<1,pos,x,L,mid); else modify(id<<1|1,pos,x,mid+1,R); mmax[id]=max(mmax[id<<1],mmax[id<<1|1]); dis[id]=dis[id<<1]+dis[id<<1|1];}int LCA(int a,int b){ int ta=top[a],tb=top[b]; while(ta!=tb) { if(dep[ta]<dep[tb]) swap(a,b),swap(ta,tb); a=fa[ta]; ta=top[a]; } if(dep[a]<dep[b]) return a; else return b;}int getmax(int a,int b){ int ta=top[a],tb=top[b]; int ans=w[a]; while(ta!=tb) { ans=max(ans,query1(1,fc[ta],fc[a],1,cnt)); a=fa[ta]; ta=top[a]; } if(a!=b) { ans=max(ans,query1(1,fc[b],fc[a],1,cnt)); } ans=max(ans,w[b]); return ans;}int getdis(int a,int b){ int ta=top[a],tb=top[b]; int ans=0; while(ta!=tb) { ans+=query2(1,fc[ta],fc[a],1,cnt); a=fa[ta]; ta=top[a]; } ans+=query2(1,fc[b],fc[a],1,cnt); return ans;}/////////////////////////////////////////////////void input(){ MS(head,-1); scanf("%d",&n); int u,v; rep(i,1,n-1) { scanf("%d%d",&u,&v); adde(u,v); adde(v,u); } rep(i,1,n) { scanf("%d",&w[i]); } scanf("%d",&q);}void solve(){ ///////////////////init/////////////////// char op[10]; int u,v; ////////////////calculate//////////////// // init HLT dfs1(1,w[1]); dfs2(1,1); build(1,1,n); rep(i,1,n) modify(1,fc[i],w[i],1,n); /*rep(i,1,n) printf("%d\n",query(1,fc[i],fc[i],1,cnt)); return;*/ // query while(q--) { scanf("%s%d%d",op,&u,&v); if(op[0]=='C')//CHANGE { w[u]=v; modify(1,fc[u],v,1,n); } else { int lca=LCA(u,v); if(op[1]=='M') //QMAX { int ans=getmax(u,lca); ans=max(ans,getmax(v,lca)); printf("%d\n",ans); } else ///QSUM { int ans=getdis(u,lca)+getdis(v,lca); ans-=w[lca]; printf("%d\n",ans); } } } /////////////////output///////////////// }/////////////////////////////////////////////////int main(){ #ifndef _TEST freopen("1036.in","r",stdin); freopen("1036.out","w",stdout); #endif input(); solve(); #ifdef _TEST for(;;); #endif return 0;}
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 树链剖分
- 【bzoj1036】【树链剖分】 [ZJOI2008]树的统计Count
- [Bzoj1036][ZJOI2008]树的统计Count
- 【BZOJ1036】【ZJOI2008】树的统计Count 树链剖分裸题
- 【ZJOI2008】【BZOJ1036】树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count && LCT
- bzoj1036: [ZJOI2008]树的统计Count
- 编译Android源码与内核总结
- CUDA入门教程(一)
- Implementing SoD in SQL Server
- 第八周项目4
- VMware-Fusion-7.0.0-2103067 Pro SN:序列号+ 百度云下载地址
- 【树链剖分模板】【bzoj1036】: [ZJOI2008]树的统计Count
- Struts2中ActionContext介紹 && Struts2如何获得request
- GeoServer+OpenLayers发布下载的Google卫星影像
- phpnow轻松添加虚拟主机
- Ubuntu安装时没注册root用户密码,怎么登录root
- Epoll高并发通讯类
- [Android]Android中全屏或者取消标题栏
- No supported iOS devices are available
- Linux下的进程间通信-详解