记录编号 303719 评测结果 AAAAAWWWWW
题目名称 [HAOI 2015]树上操作 最终得分 50
用户昵称 GravatarGo灬Fire 是否通过 未通过
代码语言 C++ 运行时间 2.164 s
提交时间 2016-09-06 16:18:45 内存使用 25.66 MiB
显示代码纯文本
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define LL long long
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r 
using namespace std;
const int maxn=100001;
struct Edge{
    int to,next;
}e[maxn<<4];
struct Node{
    int date,lazy;
}a[maxn<<4];
int head[maxn],len,root[maxn],son[maxn],size[maxn],id[maxn],pos[maxn];
int deep[maxn],top[maxn],ra[maxn],cnt,n,m,Qx,Qy,v[maxn],res;
void Insert(int x,int y){//建边 
    len++;e[len].to=y;e[len].next=head[x];head[x]=len;
}
void Dfs1(int);
//求size 以自己为根的包括自己的节点总数,son所有儿子中权值最大的儿子,即重儿子,deep 该节点的深度,root 该节点的父亲 
void Dfs2(int,int); 
//求ra  以x为根的子节点的结尾叶子节点 ,id  节点x在树链中的位置,top 节点x所在重链最上面的节点,如果x不在重链上,则top【x】=x,pos记录它本来的位置 
//两个Dfs求各个数组
void Update(int,int,int);//传递lazy值
void Build(int,int,int);//正式建树

int tree_query(int,int);
int Query(int,int);
void Query(int,int,int);//求任意节点到节点1的所有点的权值和 
 
void Change(int,int,int,int,int);//改变一个节点的权值,给此节点的权值+t
void add(int,int,int,int,int,int); //把某个节点x为根的子树中所有点的点权都增加a。
 
int main(){
    freopen("haoi2015_t2.in","r",stdin);
    freopen("haoi2015_t2.out","w",stdout);
    scanf("%d%d",&n,&m);//点数为n的树,以1为节点,m次操作
    deep[1]=1;
    for(int i=1;i<=n;i++)scanf("%d",&v[i]);//每个节点的权值
    for(int i=1;i<n;i++){//n-1条边 
        int x,y;scanf("%d%d",&x,&y);
        Insert(x,y);Insert(y,x);
    } 
    Dfs1(1);
    Dfs2(1,1);
    Build(1,1,n); 
    int type,x,a;
    for(int i=1;i<=m;i++){
        scanf("%d",&type);
        if(type==1){//改变一个节点的权值,给此节点的权值+a
            scanf("%d%d",&x,&a);
            Change(id[x],a,1,1,n);
        }
        if(type==2){//把某个节点x为根的子树中所有点的点权都增加a。
            scanf("%d%d",&x,&a);
            add(id[x],ra[x],a,1,1,n); 
        }
        if(type==3){
            scanf("%d",&x);
            printf("%d\n",tree_query(1,x));
        }
    }
    //system("pause");
    return 0;
} 
void Dfs1(int x){
    size[x]=1;son[x]=0;
    for(int i=head[x];i;i=e[i].next){
        int p=e[i].to;
        if(p!=root[x]){
            root[p]=x;deep[p]=deep[x]+1;
            Dfs1(p);
            size[x]+=size[p];
            if(size[p]>size[son[x]])son[x]=p;
        }
    } 
}
void Dfs2(int x,int tp){
    top[x]=tp;id[x]=++cnt;pos[cnt]=x;
    if(son[x])Dfs2(son[x],tp);
    for(int i=head[x];i;i=e[i].next){
        int k=e[i].to;
        if(root[x]!=k && son[x]!=k)Dfs2(k,k);
    }
    ra[x]=cnt;
} 
void Build(int rt,int l,int r){
    if(l==r){
        a[rt].date=v[pos[l]];return;
    }
    int mid=(l+r)>>1;
    Build(lson);Build(rson);
    a[rt].date=a[rt<<1].date+a[rt<<1|1].date;
}
void Update(int rt,int l,int r){
    int x=a[rt].lazy;
    int mid=(l+r)>>1;
    a[rt<<1].lazy+=x;a[rt<<1|1].lazy+=x;
    a[rt<<1].date+=x*(mid-l+1);a[rt<<1|1].date+=x*(r-mid);
    a[rt].lazy=0;
}
void Change(int x,int z,int rt,int l,int r){
    if(l==r){
        a[rt].date+=z;return;
    }
    int mid=(l+r)>>1;
    if(a[rt].lazy)Update(rt,l,r);
    if(x<=mid)Change(x,z,lson);
    else Change(x,z,rson);
    a[rt].date=a[rt<<1].date+a[rt<<1|1].date;
}
void add(int s,int t,int z,int rt,int l,int r){
    if(s<=l && t>=r){a[rt].date+=(r-l+1)*z;a[rt].lazy+=z;return;}
    int mid=(l+r)>>1;
    if(a[rt].lazy)Update(rt,l,r);
    if(s<=mid)add(s,t,z,lson);
    if(t>mid)add(s,t,z,rson);
    a[rt].date=a[rt<<1].date+a[rt<<1|1].date;
}
int tree_query(int x,int y){
    int fx=top[x],fy=top[y],ans=0;
    while(fx!=fy){
        if(deep[fx]<deep[fy]){swap(x,y);swap(fx,fy);}
        ans+=Query(id[fx],id[x]);
        x=root[fx];fx=top[x];
    }
    if(deep[x]>deep[y])swap(x,y);
    ans+=Query(id[x],id[y]);
    return ans;
}
int Query(int s,int t){
    Qx=s;Qy=t;res=0;
    Query(1,1,n);
    return res;
}
void Query(int rt,int l,int r){
    if(Qx<=l && Qy>=r){
        res+=a[rt].date;return;
    }
    int mid=(l+r)>>1;
    if(a[rt].lazy)Update(rt,l,r);
    if(Qx<=mid)Query(lson);
    if(Qy>mid)Query(rson);
    a[rt].date=a[rt<<1].date+a[rt<<1|1].date;
}