zoukankan      html  css  js  c++  java
  • 【HAOI2015】树上操作-树链剖分

    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

    【数据约定】
    对于30的数据,N,M<=1000;
    对于50%的数据,N,M<=100000且数据随机;
    对于100%的数据,N,M<=100000,且所有输入数据的绝对值都不会超过10^6。


    思路

    • 对于操作二:id[x]到id[x]+size[x] - 1进行区间修改
    • 区分边权和点权,asksum是num[son[u]]还是num[u]
    • 重构前30分光荣阵亡,重构后一遍AC

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define maxn 100005
    #define int long long 
    using namespace std;
    int n,m,cnt,head[maxn],val[maxn];
    struct node{int next,to;}e[maxn<<1];
    struct fdfdfd{int l,r,len,sum,flag;}a[maxn<<2];
    int son[maxn],fa[maxn],num[maxn],fnum[maxn],top[maxn],deep[maxn],siz[maxn];
    void addedge(int x,int y){e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;}
    void dfs_1(int u,int pre)
    {
    	fa[u]=pre; deep[u]=deep[pre]+1; siz[u]=1;
    	for(int i=head[u];i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if(v!=fa[u])
    		{
    			dfs_1(v,u); siz[u]+=siz[v];
    			if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v;
    		}
    	}
    }
    void dfs_2(int u,int topp)
    {
    	top[u]=topp; num[u]=++cnt; fnum[cnt]=u;
    	if(son[u]!=-1) dfs_2(son[u],topp);
    	for(int i=head[u];i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if(v!=fa[u]&&v!=son[u]) dfs_2(v,v);
    	}
    }
    void pushup(int x){a[x].sum=a[x<<1].sum+a[x<<1|1].sum;}
    void pushdown(int x)
    {
    	if(!a[x].flag) return;
    	a[x<<1].flag+=a[x].flag; a[x<<1].sum+=a[x<<1].len*a[x].flag;
    	a[x<<1|1].flag+=a[x].flag; a[x<<1|1].sum+=a[x<<1|1].len*a[x].flag;
    	a[x].flag=0;
    }
    void build(int x,int left,int right)
    {
    	a[x].l=left; a[x].r=right; a[x].len=right-left+1;
    	if(left==right) return;
    	int mid=(left+right)>>1;
    	build(x<<1,left,mid); build(x<<1|1,mid+1,right);
    }
    void insert(int x,int v,int d)
    {
    	if(a[x].r<v||a[x].l>v) return;
    	if(a[x].l==v&&a[x].r==v) {a[x].sum+=d; return;}
    	pushdown(x);
    	insert(x<<1,v,d); insert(x<<1|1,v,d);
    	pushup(x);
    }
    void modify(int x,int left,int right,int d)
    {
    	if(a[x].r<left||a[x].l>right) return;
    	if(left<=a[x].l&&right>=a[x].r)
    	{
    		a[x].sum+=d*a[x].len; a[x].flag+=d;
    		return;
    	}
    	pushdown(x);
    	modify(x<<1,left,right,d); modify(x<<1|1,left,right,d);
    	pushup(x);
    }
    int query(int x,int left,int right)
    {
    	if(a[x].r<left||a[x].l>right) return 0;
    	if(left<=a[x].l&&right>=a[x].r) return a[x].sum;
    	pushdown(x);
    	return query(x<<1,left,right)+query(x<<1|1,left,right);
    }
    int asksum(int u,int v)
    {
    	int ans=0;
    	while(top[u]!=top[v])
    	{
    		if(deep[top[u]]<deep[top[v]]) swap(u,v);
    		ans+=query(1,num[top[u]],num[u]);
    		u=fa[top[u]];
    	}
    	if(deep[u]>deep[v]) swap(u,v);
    	ans+=query(1,num[u],num[v]);
    	return ans;
    }
    signed main()
    {
    	memset(son,-1,sizeof(son));
    	scanf("%lld%lld",&n,&m);
    	for(int i=1;i<=n;++i) scanf("%lld",&val[i]);
    	for(int i=1,u,v;i<n;++i) scanf("%lld%lld",&u,&v),addedge(u,v),addedge(v,u);
    	dfs_1(1,0); cnt=0; dfs_2(1,1); build(1,1,n);
    	for(int i=1;i<=n;++i) insert(1,num[i],val[i]);
    	while(m--)
    	{
    		int op,x,w; scanf("%lld%lld",&op,&x);
    		if(op==1) scanf("%lld",&w),insert(1,num[x],w);
    		else if(op==2) scanf("%lld",&w),modify(1,num[x],num[x]+siz[x]-1,w);
    		else printf("%lld
    ",asksum(x,1));
    	}
    	return 0;
    }
    
  • 相关阅读:
    C++学习9 this指针详解
    福建省第八届 Triangles
    UVA 11584 Partitioning by Palindromes
    POJ 2752 Seek the Name, Seek the Fame
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    HDU 2988 Dark roads(kruskal模板题)
    HDU 1385 Minimum Transport Cost
    HDU 2112 HDU Today
    HDU 1548 A strange lift(最短路&&bfs)
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13478266.html
Copyright © 2011-2022 走看看