1036: [ZJOI2008]树的统计Count 树链剖分+线段树
来源:互联网 发布:中国网络为什么多喷子 编辑:程序博客网 时间:2024/05/16 18:46
题目大意:给出一棵树,每个点有一个权值,要求三种操作:1.修改某个点的权值,2.询问x到y路径上各点的权值最大值,3.询问x到y路径上各点的权值之和。
算法讨论:树链剖分模板题。
题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1036
#include<stdio.h>#include<string.h>#include<algorithm>#define N 30005#define inf 0x3fffffffusing namespace std;struct node{ int u,v,next;} bian[N*2];struct pp{ int x,y,max,sum;} a[N*3];int ma(int a,int b){ return a>b?a:b;}int e,dep[N],sz[N],father[N],son[N],top[N],head[N],ti[N],id;void add(int u,int v){ bian[e].u=u; bian[e].v=v; bian[e].next=head[u]; head[u]=e++;}void dfs1(int u,int fa){ int i,v; dep[u]=dep[fa]+1; sz[u]=1; father[u]=fa; son[u]=0; for(i=head[u]; i!=-1; i=bian[i].next) { v=bian[i].v; if(v==fa) continue; dfs1(v,u); sz[u]+=sz[v]; if(sz[son[u]]<sz[v]) son[u]=v; }}void dfs2(int u,int fa){ int i,v; ti[u]=id++; top[u]=fa; if(son[u]!=0) dfs2(son[u],fa); for(i=head[u]; i!=-1; i=bian[i].next) { v=bian[i].v; if(v==son[u]||v==father[u]) continue; dfs2(v,v); }}void build(int t,int x,int y){ a[t].x=x; a[t].y=y; a[t].max=a[t].sum=0; if(x==y) return; int mid=(x+y)>>1,temp=t<<1; build(temp,x,mid); build(temp+1,mid+1,y);}void update(int t,int x,int w){ if(a[t].x==a[t].y) { a[t].max=a[t].sum=w; return; } int mid=(a[t].x+a[t].y)>>1,temp=t<<1; if(x<=mid) update(temp,x,w); else update(temp+1,x,w); a[t].sum=a[temp].sum+a[temp+1].sum; a[t].max=ma(a[temp].max,a[temp+1].max);}int query(int x,int y,int t,int flag){ if(a[t].x==x&&a[t].y==y) { if(flag==0) return a[t].max; else return a[t].sum; } int mid=(a[t].x+a[t].y)>>1,temp=t<<1; if(y<=mid) return query(x,y,temp,flag); else if(x>mid) return query(x,y,temp+1,flag); else { if(flag==0) return ma(query(x,mid,temp,flag),query(mid+1,y,temp+1,flag)); else return query(x,mid,temp,flag)+query(mid+1,y,temp+1,flag); }}int lca(int x,int y,int flag){ int ans=-inf, sum=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); if(flag==0) ans=ma(ans,query(ti[top[x]],ti[x],1,flag)); else sum+=query(ti[top[x]],ti[x],1,flag); x=father[top[x]]; } if(dep[x]>dep[y]) swap(x,y); if(flag==0) ans=ma(ans,query(ti[x],ti[y],1,flag)); else sum+=query(ti[x],ti[y],1,flag); if(flag==0) return ans; else return sum;}int main(){ int n,i,u,v,w,q,x,y; char str[100]; while(scanf("%d",&n)!=EOF) { e=0; memset(head,-1,sizeof(head)); for(i=1; i<n; i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } dep[1]=0; sz[0]=0; id=1; dfs1(1,1); dfs2(1,1); build(1,1,n); //for(i=1; i<=n; i++) // printf("i=%d ti=%d dep=%d sz=%d son=%d top=%d father=%d\n",i,ti[i],dep[i],sz[i],son[i],top[i],father[i]); for(i=1; i<=n; i++) { scanf("%d",&w); update(1,ti[i],w); } scanf("%d",&q); while(q--) { scanf("%s %d %d",str,&x,&y); if(strcmp(str,"QMAX")==0) printf("%d\n",lca(x,y,0)); else if(strcmp(str,"QSUM")==0) printf("%d\n",lca(x,y,1)); else update(1,ti[x],y); } } return 0;}
0 0
- 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 树链剖分+线段树
- 【bzoj1036】[ZJOI2008]树的统计Count 树链剖分+线段树
- 【BZOJ1036】[ZJOI2008]树的统计Count(树链剖分+线段树)
- 【树链剖分+线段树】BZOJ1036 [ZJOI2008]树的统计Count
- BZOJ1036(ZJOI2008)[树的统计Count]--树链剖分+线段树
- BZoj 1036: [ZJOI2008]树的统计Count【树链剖分+线段树--模板题】
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- bzoj 1036 [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- BZOJ-1036: [ZJOI2008]树的统计Count (树链剖分 线段树 单点修改 区间查询 入门题)
- 文章标题 BZOJ 1036 : [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- Burning Midnight Oil+二分答案+codeforces
- hd 2018 母牛的故事
- QT常用例程收集整理(易集成至主工程)
- 编辑文章 - 博客频道 - CSDN.NET
- mysql OUTFILE 与 LOAD DATA
- 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- php str_replace还可以这么用。。。厉害
- gcc 与g++的区别
- MIT高级讲师:从大数据到深数据
- 301永久重定向的各种做法
- Json转换利器Gson之实例三-Map处理上
- TCP协议中的三次握手和四次挥手(图解)
- 杭电 1800 Flying to the Mars(贪心)
- pop回去第几个controller