• luoguP2590 [ZJOI2008]树的统计(树链剖分)


    luogu P2590 [ZJOI2008]树的统计 题目

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iomanip>
    #include<algorithm>
    #include<ctime>
    #include<queue>
    #define rg register
    #define lst long long
    #define N 30050
    #define ls (now<<1)
    #define rs (now<<1|1)
    using namespace std;
    
    int n,Q,cnt,ss,root,ans;
    struct EDGE{
        int to,nxt;
    }edge[N<<1];
    struct TREE{
        int l,r,Max,sum;
    }ljl[N<<2];
    int v[N],head[N];
    int fa[N],deep[N],size[N],num[N];
    int vv[N],top[N],son[N];
    
    inline void add(rg int p,rg int q){edge[++cnt]=(EDGE){q,head[p]};head[p]=cnt;}
    inline int read()
    {
        rg int s=0,m=1;rg char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')m=-1,ch=getchar();
        while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        return s*m;
    }
    
    inline void init()
    {
        n=read();root=1;
        for(rg int i=1;i<n;++i)
        {
            rg int p=read(),q=read();
            add(p,q),add(q,p);
        }
        for(rg int i=1;i<=n;++i)v[i]=read();
    }
    
    void dfs_1(rg int now,rg int fm,rg int dep)
    {
        rg int kk=0;
        fa[now]=fm,deep[now]=dep,size[now]=1;
        for(rg int i=head[now];i;i=edge[i].nxt)
        {
            rg int qw=edge[i].to;
            if(qw!=fm)
            {
                dfs_1(qw,now,dep+1);
                size[now]+=size[qw];
                if(size[qw]>kk)kk=size[qw],son[now]=qw;
            }
        }
    }
    
    void dfs_2(rg int now,rg int up)
    {
        num[now]=++ss,vv[ss]=v[now],top[now]=up;
        if(son[now])dfs_2(son[now],top[now]);
        for(rg int i=head[now];i;i=edge[i].nxt)
        {
            rg int qw=edge[i].to;
            if(qw!=fa[now]&&qw!=son[now])
                dfs_2(qw,qw);
        }
    }
    
    inline void Pushup(rg int now)
    {
        ljl[now].Max=max(ljl[ls].Max,ljl[rs].Max);
        ljl[now].sum=ljl[ls].sum+ljl[rs].sum;
    }
    
    void build(rg int now,rg int ll,rg int rr)
    {
        ljl[now]=(TREE){ll,rr};
        if(ll==rr)
        {
            ljl[now].Max=ljl[now].sum=vv[ll];
            return;
        }
        rg int mid=(ll+rr)>>1;
        build(ls,ll,mid),build(rs,mid+1,rr);
        Pushup(now);
    }
    
    void change(rg int now,rg int kk,rg int x)
    {
        if(ljl[now].l==kk&&ljl[now].r==kk)
        {
            ljl[now].Max=ljl[now].sum=x;
            return;
        }
        rg int mid=(ljl[now].l+ljl[now].r)>>1;
        if(kk<=mid)change(ls,kk,x);
        else change(rs,kk,x);
        Pushup(now);
    }
    
    int get_max(rg int now,rg int ll,rg int rr)
    {
        rg int ss=-1e9;
        if(ljl[now].l>=ll&&ljl[now].r<=rr)return ljl[now].Max;
        rg int mid=(ljl[now].l+ljl[now].r)>>1;
        if(rr<=mid)ss=max(ss,get_max(ls,ll,rr));
        if(ll>mid) ss=max(ss,get_max(rs,ll,rr));
        if(ll<=mid&&rr>mid)ss=max(ss,max(get_max(ls,ll,mid),get_max(rs,mid+1,rr)));
        return ss;
    }
    
    int get_sum(rg int now,rg int ll,rg int rr)
    {
        rg int ss=0;
        if(ljl[now].l>=ll&&ljl[now].r<=rr)return ljl[now].sum;
        rg int mid=(ljl[now].l+ljl[now].r)>>1;
        if(rr<=mid)ss+=get_sum(ls,ll,rr);
        if(ll>mid) ss+=get_sum(rs,ll,rr);
        if(ll<=mid&&rr>mid)ss+=get_sum(ls,ll,mid)+get_sum(rs,mid+1,rr);
        return ss;
    }
    
    inline void work(rg int x,rg int y,rg int op)
    {
        if(num[x]>num[y])swap(x,y);
        if(!op)ans=max(ans,get_max(1,num[x],num[y]));
        if(op) ans+=get_sum(1,num[x],num[y]);
    }
    
    inline void Work(rg int x,rg int y,rg int op)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            work(top[x],x,op);
            x=fa[top[x]];
        }
        work(x,y,op);
    }
    
    inline void Ans()
    {
        Q=read();
        for(rg int i=1;i<=Q;++i)
        {
            char type[6];cin>>type;
            rg int x=read(),y=read();
            if(type[3]=='N'){         change(1,num[x],y);}//change
            if(type[3]=='X'){ans=-1e9;Work(x,y,0);printf("%d
    ",ans);}//qmax
            if(type[3]=='M'){ans=0;   Work(x,y,1);printf("%d
    ",ans);}//qsum
        }
    }
    
    int main()
    {
        init();
        dfs_1(root,0,0);
        dfs_2(root,root);
        build(1,1,n);
        Ans();
        return 0;
    }
  • 相关阅读:
    函数指针作为函数參数,实现冒泡排序的升序排序和降序排序
    为什么通过空指针(NULL)能够正确调用类的部分成员函数
    vc6.0 点编译时提示Cannot complile the file &#39;D:souce-codevc-workspace对话框MainFrm.h&#39;; no compile tool is
    struts2中Action訪问servlet的两种方式
    删除LINUX更新后多余的内核
    cocos2d-x 3.0rc2版公布了
    The user specified as a definer (&#39;root&#39;@&#39;%&#39;) does not exist
    HDU 4287 Intelligent IME(map运用)
    HDU 4925 Apple Tree(推理)
    Linux下使用Fastboot给手机刷ROM
  • 原文地址:https://www.cnblogs.com/cjoierljl/p/9107490.html
Copyright © 2020-2023  润新知