Bzoj 1036: [ZJOI2008]树的统计Count
来源:互联网 发布:美国滑板鞋牌子 知乎 编辑:程序博客网 时间:2024/05/16 08:42
题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=1036
题解:
树链剖分+线段树操作
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define met(a,b) memset(a,b,sizeof(a))#define inf 0x7fffffffconst int maxn = 30005;struct EDGE{ int to,next;}Edge[maxn*2];struct Tree{ int left,right; int sum,MAX;}tree[maxn<<2];int head[maxn];int cnt;void init1(){ cnt=0; met(head,-1);}void Add_edge(int u,int v){ Edge[++cnt].to=v,Edge[cnt].next=head[u],head[u]=cnt; Edge[++cnt].to=u,Edge[cnt].next=head[v],head[v]=cnt;}int size[maxn],fa[maxn],deep[maxn];void init2(){ met(size,0),met(fa,0),met(deep,0);}//size[i]:表示i这个节点下面的字节点的个数void Dfs1(int x){ size[x]=1; for(int i=head[x];i!=-1;i=Edge[i].next) { if(Edge[i].to==fa[x]) continue; deep[Edge[i].to]=deep[x]+1; fa[Edge[i].to]=x; Dfs1(Edge[i].to); size[x]+=size[Edge[i].to]; }}int bl[maxn],pos[maxn];int sz;void init3(){ sz=0; met(bl,0),met(pos,0);}//pos[i]:表示i这个节点在线段树的位置void Dfs2(int x,int chain){ int k=0; sz++; pos[x]=sz;//分配在线段树里的位置 bl[x]=chain; for(int i=head[x];i!=-1;i=Edge[i].next) { if(deep[Edge[i].to]>deep[x]&&size[Edge[i].to]>size[k]) k=Edge[i].to;//选择子树中的最大的儿子来继承重链 } if(k==0) return; Dfs2(k,chain); for(int i=head[x];i!=-1;i=Edge[i].next) { if(deep[Edge[i].to]>deep[x]&&k!=Edge[i].to) Dfs2(Edge[i].to,Edge[i].to); }}//-------线段树void build(int rt,int l,int r){ tree[rt].left=l; tree[rt].right=r; if(l==r)return; int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);}void updata(int rt,int pos,int delta){ int left=tree[rt].left,right=tree[rt].right; int mid=(left+right)>>1; if(left==right) { tree[rt].sum=tree[rt].MAX=delta; return; } if(pos<=mid) updata(rt<<1,pos,delta); else updata(rt<<1|1,pos,delta); tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; tree[rt].MAX=max(tree[rt<<1].MAX,tree[rt<<1|1].MAX);}int querysum(int x,int y,int rt){ int left=tree[rt].left,right=tree[rt].right,mid=(left+right)>>1; if(left==x&&right==y) return tree[rt].sum; if(y<=mid) return querysum(x,y,rt<<1); else if(x>mid) return querysum(x,y,rt<<1|1); else return querysum(x,mid,rt<<1)+querysum(mid+1,y,rt<<1|1);}int querymax(int x,int y,int rt){ int left=tree[rt].left,right=tree[rt].right,mid=(left+right)>>1; if(left==x&&right==y) return tree[rt].MAX; if(y<=mid) return querymax(x,y,rt<<1); else if(x>mid) return querymax(x,y,rt<<1|1); else return max(querymax(x,mid,rt<<1),querymax(mid+1,y,rt<<1|1));}int slovemax(int x,int y){ int MAX=-inf; while(bl[x]!=bl[y]) { if(deep[bl[x]]<deep[bl[y]]) swap(x,y); MAX=max(MAX,querymax(pos[bl[x]],pos[x],1)); x=fa[bl[x]]; } if(pos[x]>pos[y]) swap(x,y); MAX=max(MAX,querymax(pos[x],pos[y],1)); return MAX;}int slovesum(int x,int y){ int sum=0; while(bl[x]!=bl[y]) { if(deep[bl[x]]<deep[bl[y]]) swap(x,y); sum+=querysum(pos[bl[x]],pos[x],1); x=fa[bl[x]]; } if(pos[x]>pos[y]) swap(x,y); sum+=querysum(pos[x],pos[y],1); return sum;}int room[maxn];int main(){ int n; scanf("%d",&n); init1(),init2(),init3(); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); Add_edge(x,y); } met(room,0); for(int i=1;i<=n;i++) scanf("%d",&room[i]); Dfs1(1); Dfs2(1,1); build(1,1,n); for(int i=1;i<=n;i++) updata(1,pos[i],room[i]); int m; scanf("%d",&m); char s[maxn]; int x,y; while(m--) { scanf("%s%d%d",s,&x,&y); if(strcmp(s,"CHANGE")==0) updata(1,pos[x],y); else if(strcmp(s,"QMAX")==0) printf("%d\n",slovemax(x,y)); else printf("%d\n",slovesum(x,y)); } return 0;}
阅读全文
0 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
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count
- 【bzoj】1036: [ZJOI2008]树的统计Count
- [BZOJ]1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008] 树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- 【bzoj 1036】 [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- Bzoj 1036: [ZJOI2008]树的统计Count
- 解密Spring Boot整合Dubbo RPC框架
- Win 10 + CodeBlocks 配置 OpenGL
- LeetCode100. Same Tree
- C#一个服务器端多个客户端Socket通信
- bzoj 1123 BLO
- Bzoj 1036: [ZJOI2008]树的统计Count
- < 笔记 > Git
- OpenCV示例学习笔记(1)-contours2.cpp-通过findContours 函数实现轮廓提取
- CentOS7 安装 vlc
- 正则元字符
- Netty基本组件模型简单说明
- springboot 使用jsp 打包后无法访问
- 2017NOIP普及组初赛感想
- Source Insight 4.0.008最新版体验用法和破解下载地址