BZOJ 4034 :[HAOI2015]树上操作 树链剖分裸题
来源:互联网 发布:淘宝api 获取卖家订单 编辑:程序博客网 时间:2024/06/06 12:58
4034: [HAOI2015]树上操作
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 4744 Solved: 1513
[Submit][Status][Discuss]
Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1
行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中
第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
Sample Output
6
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。
这道题显然是一道树链剖分裸题,有一点值得注意,就是第二个操作的处理,其实我们可以发现,对于一棵子树的修改,我们可以发现,这棵子树中所有点的序号是连续的,所以我们可以记录一个该子树中序号最大的点,就可以进行操作了
#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<vector>#include<map>#include<set>#define dnt long longconst int MAXN = 100000+10;using namespace std;int readin(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}dnt val[MAXN];struct Line{ int from,to,nxt;}line[MAXN*2+10];int N,M,tail;int head[MAXN];int mx[MAXN],top[MAXN],dep[MAXN],siz[MAXN],son[MAXN],fa[MAXN],tid[MAXN],timer,rank[MAXN];dnt sum[MAXN*4+10],mark[MAXN*4+10];void add_line(int from,int to){ tail++; line[tail].from=from; line[tail].to=to; line[tail].nxt=head[from]; head[from]=tail;}void dfs1(int u,int father,int d){ fa[u]=father; dep[u]=d; siz[u]=1; for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(v!=father){ dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[son[u]]<siz[v]) son[u]=v; } }}void dfs2(int u,int tp){ tid[u]=mx[u]=++timer; rank[tid[u]]=u; top[u]=tp; if(son[u]==-1) return; dfs2(son[u],tp);mx[u]=max(mx[u],mx[son[u]]); for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(v!=son[u]&&v!=fa[u]){ dfs2(v,v); mx[u]=max(mx[u],mx[v]); } }}void pushup(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void pushdown(int rt,int len){ if(mark[rt]){ mark[rt<<1]+=mark[rt]; mark[rt<<1|1]+=mark[rt]; sum[rt<<1]+=(len-(len>>1))*mark[rt]; sum[rt<<1|1]+=(len>>1)*mark[rt]; mark[rt]=0; }}void build(int l,int r,int rt){ mark[rt]=0; if(l==r){ sum[rt]=val[rank[l]]; return; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt);}void modify(int L,int R,dnt add,int l,int r,int rt){ if(L<=l&&R>=r){ mark[rt]+=add; sum[rt]+=(r-l+1)*add; return; } pushdown(rt,r-l+1); int mid=(l+r)>>1; if(L<=mid) modify(L,R,add,l,mid,rt<<1); if(R>mid) modify(L,R,add,mid+1,r,rt<<1|1); pushup(rt);}dnt query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r){ return sum[rt]; } pushdown(rt,r-l+1); int mid=(l+r)>>1; dnt sumn=0; if(L<=mid) sumn+=query(L,R,l,mid,rt<<1); if(R>mid) sumn+=query(L,R,mid+1,r,rt<<1|1); return sumn; }dnt _query(int from,int to){ dnt ans=0; while(top[from]!=top[to]){ if(dep[top[from]]<dep[top[to]]) swap(from,to); ans+=query(tid[top[from]],tid[from],1,N,1); from=fa[top[from]]; } if(dep[from]<dep[to]) swap(from,to); ans+=query(tid[to],tid[from],1,N,1); return ans;}int main(){ freopen("BZOJ4034.txt","r",stdin); //freopen(".out","w",stdout); int f,t; memset(son,-1,sizeof(son)); scanf("%d%d",&N,&M); for(register int i=1;i<=N;i++) scanf("%lld",&val[i]); for(register int i=1;i<=N-1;i++){ scanf("%d%d",&f,&t); add_line(f,t); add_line(t,f); } dfs1(1,0,0); dfs2(1,1); build(1,N,1); for(register int i=1;i<=M;i++){ int opt,te; dnt mp; scanf("%d",&opt); if(opt==1){ scanf("%d%lld",&te,&mp); modify(tid[te],tid[te],mp,1,N,1); }else if(opt==2){ scanf("%d%lld",&te,&mp); modify(tid[te],mx[te],mp,1,N,1); }else{ scanf("%d",&te); mp=_query(1,te); printf("%lld\n",mp); } } return 0;}
阅读全文
0 0
- BZOJ 4034 :[HAOI2015]树上操作 树链剖分裸题
- BZOJ 4034 [HAOI2015]树上操作
- bzoj 4034 [HAOI2015]树上操作
- 【BZOJ 4034】 [HAOI2015]树上操作
- BZOJ 4034: [HAOI2015]树上操作
- bzoj 4034 [HAOI2015]树上操作
- BZOJ 4034 [HAOI2015]树上操作
- bzoj 4034: [HAOI2015]树上操作 (树链剖分)
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- BZOJ 4034 [HAOI2015]树上操作 树链剖分
- bzoj 4034: [HAOI2015]树上操作 树链剖分
- bzoj P4034 [HAOI2015]树上操作
- 4034: [HAOI2015]树上操作
- |BZOJ 4034|树链剖分|线段树|[HAOI2015]树上操作
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
- BZOJ[4034][HAOI2015]树上操作 树链剖分+线段树
- bzoj 4034: [HAOI2015]树上操作(线段树+dfs序)
- [树链剖分]bzoj 4034—— [HAOI2015]树上操作
- PHP学习之路(一)认识php数变量和变量声明
- C# 解析XML
- 点集直径和旋转卡壳
- SAP product set type
- mysql使用union顺序混乱
- BZOJ 4034 :[HAOI2015]树上操作 树链剖分裸题
- 区间选点问题
- javascript字符串方法汇总
- [LeetCode] 342. Power of Four
- Linux shell ${}简单用法
- 不容错过,最全的安卓架构合集-(从零开始搭建android框架系列(2))
- 谈谈对Spring IOC的理解
- 小米笔记本2 Ubuntu 16.04下安装Tensorflow GPU 1.2.1版本说明
- Tomcat -- 多个Context启动冲突的问题解决