• 树链剖分练习总结


    刷完了网上的树剖练习...下面放代码,详细题解看树剖分类里的随笔吧。

    最后一个SDOI旅行没有做..蒟蒻好像做不了...

    T1 洛谷p3384树链剖分模板

    传送门

    题目大意:1 区间加 2 区间和 3子树加 4子树和

    代码:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int maxn=500005;
    typedef long long LL;
    int n,m,u,v,t,r,sumedge,temp;
    LL mod;
    int head[maxn],son[maxn],dad[maxn],top[maxn],heavy_son[maxn];
    int id[maxn],real[maxn],depth[maxn],a[maxn];
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn];
    struct segment_tree{
        LL l,r,sum,tag;
    }tr[maxn];
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    void dfs1(int k,int fa){
        dad[k]=fa;depth[k]=depth[fa]+1;
        son[k]=1;
        for(int i=head[k];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=fa){
                dfs1(v,k);
                son[k]+=son[v];
                if(!heavy_son[k]||son[heavy_son[k]]<son[v])
                heavy_son[k]=v;
            }
        }
    }
    void dfs2(int k,int fir){
        top[k]=fir;id[k]=++temp;
        real[temp]=k;
        if(!heavy_son[k])return;
        dfs2(heavy_son[k],fir);
        for(int i=head[k];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[k]&&v!=heavy_son[k])
            dfs2(v,v);
        }
    }
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
    }
    void pushdown(int rt){
        tr[rt<<1].tag+=tr[rt].tag;
        tr[rt<<1].sum+=tr[rt].tag*(tr[rt<<1].r-tr[rt<<1].l+1);
        tr[rt<<1|1].tag+=tr[rt].tag;
        tr[rt<<1|1].sum+=tr[rt].tag*(tr[rt<<1|1].r-tr[rt<<1|1].l+1);
        tr[rt].tag=0;
        return;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].sum=a[real[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void update(int now,int ll,int rr,int x){
        if(ll<=tr[now].l&&tr[now].r<=rr){
            tr[now].sum+=(tr[now].r-tr[now].l+1)*x;
            tr[now].tag+=x;
            return;
        }
        pushdown(now);
        int mid=(tr[now].l+tr[now].r)>>1;
        if(rr<=mid)update(now<<1,ll,rr,x);
        else if(ll>mid)update(now<<1|1,ll,rr,x);
        else {
            update(now<<1,ll,mid,x);
            update(now<<1|1,mid+1,rr,x);
        }
        pushup(now);//***
    }
    LL query_sum(int now,int ll,int rr){
        if(ll<=tr[now].l&&tr[now].r<=rr){
            return tr[now].sum;
        }
        pushdown(now);
        int mid=(tr[now].l+tr[now].r)>>1;
        if(rr<=mid)return query_sum(now<<1,ll,rr);
        else if(ll>mid)return query_sum(now<<1|1,ll,rr);
        else{
            return query_sum(now<<1,ll,mid)+query_sum(now<<1|1,mid+1,rr);
        }
    }
    void change(int u,int v,LL x){
        int tu=top[u],tv=top[v];
        while(tu!=tv){
            if(depth[tu]<depth[tv]){
                swap(tu,tv);swap(u,v);
            }
            update(1,id[tu],id[u],x);
            u=dad[tu];
            tu=top[u];
        }
        if(depth[u]>depth[v])swap(u,v);
        update(1,id[u],id[v],x);
    }
    int find_sum(int u,int v){
        LL sum=0;
        int tu=top[u],tv=top[v];
        while(tu!=tv){
            if(depth[tu]<depth[tv]){
                swap(tu,tv);
                swap(u,v);
            }
            sum+=query_sum(1,id[tu],id[u]);
            sum%=mod;
            u=dad[tu];
            tu=top[u];
        }
        if(depth[u]>depth[v])swap(u,v);
        sum+=query_sum(1,id[u],id[v]);
        return sum%mod;
    }
    
    void root_add(int now,LL x){
        int begin=id[now];
        int ed=id[now]+son[now]-1;
        update(1,begin,ed,x);
    }
    LL root_sum(int now){
        int begin=id[now];
        int ed=id[now]+son[now]-1;
        return query_sum(1,begin,ed)%mod;
    }
    
    int main(){
        scanf("%d%d%d%lld",&n,&m,&r,&mod);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        dfs1(r,0);dfs2(r,r);
        build(1,1,temp);
        for(int i=0;i<m;i++){
            int t,x,y,z;
            scanf("%d",&t);
            if(t==1){
                scanf("%d%d%d",&x,&y,&z);
                change(x,y,z);
            }else if(t==2){
                scanf("%d%d",&x,&y);
                printf("%lld
    ",find_sum(x,y));
            }else if(t==3){
                scanf("%d%d",&x,&y);
                root_add(x,y);
            }else if(t==4){
                scanf("%d",&x);
                printf("%lld
    ",root_sum(x));
            }
        }
        return 0;
    } 
    AC
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 100009
    using namespace std;
    
    int n,m,r,p,cnt,sumedge;
    
    int head[N],size[N],deep[N],dad[N],top[N],tpos[N],a[N],b[N];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[N<<2];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    struct Tree{
        int l,r,sum,s;
    }tr[N<<2];
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;dfs(v);
            size[x]+=size[v];        
        }
    }
    
    void dfs_(int x){
        int s=0;tpos[x]=++cnt;b[cnt]=a[x];
        if(!top[x])top[x]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs_(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=s&&v!=dad[x])dfs_(v);
        }
    }
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
        return ;
    }
    
    void pushdown(int rt){
        tr[rt<<1].sum=(tr[rt<<1].sum%p+(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s%p)%p;
        tr[rt<<1].s+=tr[rt].s;
        tr[rt<<1|1].sum=(tr[rt<<1|1].sum%p+(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s%p)%p;
        tr[rt<<1|1].s+=tr[rt].s;
        tr[rt].s=0;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].sum=b[l];
            return ;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void change(int rt,int l,int r,int ql,int qr,int z){
        if(l>=ql&&r<=qr){
            tr[rt].sum+=(r-l+1)*z;
            tr[rt].s+=z;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr,z);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,z);
        pushup(rt);
    }
    
    int query_sum(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr){
            return tr[rt].sum%p;
        }
        pushdown(rt);
        int ans=0,mid=(l+r)>>1;
        if(ql<=mid)ans=(ans%p+query_sum(rt<<1,l,mid,ql,qr)%p)%p;
        if(qr>mid)ans=(ans%p+query_sum(rt<<1|1,mid+1,r,ql,qr)%p)%p;
        return ans;
    }
    
    void add_(int x,int y,int z){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            change(1,1,n,tpos[top[y]],tpos[y],z);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        change(1,1,n,tpos[x],tpos[y],z);
    }
    
    int query(int x,int y){
        int ret=0;
        for(;top[x]!=top[y];){
            if(deep[top[y]]<deep[top[x]])swap(x,y);
            ret=(ret%p+query_sum(1,1,n,tpos[top[y]],tpos[y])%p)%p;
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        ret=(ret%p+query_sum(1,1,n,tpos[x],tpos[y])%p)%p;
        return ret;
    }
    
    int main(){
        scanf("%d%d%d%d",&n,&m,&r,&p);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        dfs(r);dfs_(r);build(1,1,n);
        for(int i=1;i<=m;i++){
            int od,x,y,z;
            scanf("%d",&od);
            if(od==1){
                scanf("%d%d%d",&x,&y,&z);
                add_(x,y,z);
            }
            if(od==2){
                scanf("%d%d",&x,&y);
                printf("%d
    ",query(x,y));
            }
            if(od==3){
                scanf("%d%d",&x,&z);
                change(1,1,n,tpos[x],tpos[x]+size[x]-1,z);
            }
            if(od==4){
                scanf("%d",&x);
                printf("%d
    ",query_sum(1,1,n,tpos[x],tpos[x]+size[x]-1));
            }
        }
        return 0;
    }
    后来敲的风格换了

    T2codevs4633[Mz]树链剖分练习

    传送门

    题目大意:区间加 区间和

    代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define maxn 500008
    using namespace std;
    
    int n,q,sumedge,cnt;
    int head[maxn],dad[maxn],top[maxn],deep[maxn],size[maxn],tpos[maxn];
    struct Tree{
        int l,r,sum,s;
    }tr[maxn<<2];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
        return;
    }
    
    void pushdown(int rt){
        if(!tr[rt].s)return;
        tr[rt<<1].s+=tr[rt].s;tr[rt<<1].sum+=(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s;
        tr[rt<<1|1].s+=tr[rt].s;tr[rt<<1|1].sum+=(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s;
        tr[rt].s=0;return;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        return;
    }
    
    int query_sum(int rt,int l,int r,int ql,int qr){
        pushdown(rt);
        if(l>=ql&&r<=qr){
            return tr[rt].sum;
        }
        int ans=0,mid=(l+r)>>1;
        if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr);
        if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    void change(int rt,int l,int r,int ql,int qr){
        pushdown(rt);
        if(l>=ql&&r<=qr){
            tr[rt].sum+=(tr[rt].r-tr[rt].l+1);
            tr[rt].s++;
            return;
        }
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr);
        pushup(rt);
    }
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;dfs(v);
            size[x]+=size[v];
        }
    }
    
    void dfs_(int x){
        int s=0;tpos[x]=++cnt;
        if(!top[x])top[x]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs_(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=s)dfs_(v);
        }
    }
    
    int lca(int x,int y){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])return y;
        return x;
    }
    
    void query(int x,int y){
        int ret=0;
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            ret+=query_sum(1,1,n,tpos[top[y]],tpos[y]);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        ret+=query_sum(1,1,n,tpos[x],tpos[y]);
        printf("%d
    ",ret);
    }
    
    void change_(int x,int y){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            change(1,1,n,tpos[top[y]],tpos[y]);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        change(1,1,n,tpos[x],tpos[y]);
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        dfs(1);dfs_(1);build(1,1,n);
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(a==1)change_(b,c);
            else query(b,c);
        }
        return 0;
    }
    
    AC
    AC

    T3洛谷P2590树的统计

    传送门

    题目大意:单点修改 区间和 区间最大值

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100005
    #define inf 100000000
    using namespace std;
    
    int n,q,cnt,sumedge;
    int w[maxn],size[maxn],deep[maxn],top[maxn],dad[maxn];
    int re[maxn],head[maxn],tpos[maxn];
    
    struct Tree{
        int l,r,sum,mx;
    }tr[maxn<<2];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;
            dfs(v);
            size[x]+=size[v];
        }
    }
    
    void dfs_(int x){
        tpos[x]=++cnt;re[cnt]=x;
        int s=0;
        if(!top[x])top[x]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs_(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=s)dfs_(v);
        }
    }
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
        tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx);
        return;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].sum=tr[rt].mx=w[re[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void update(int rt,int l,int r,int q,int v){
        if(l==r){
            tr[rt].sum=tr[rt].mx=v;
            return;
        }
        int mid=(l+r)>>1;
        if(q<=mid)update(rt<<1,l,mid,q,v);
        else update(rt<<1|1,mid+1,r,q,v);
        pushup(rt);
    }
    
    int querysum(int rt,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return tr[rt].sum;
        int mid=(l+r)>>1,ans=0;
        if(ql<=mid)ans+=querysum(rt<<1,l,mid,ql,qr);
        if(qr>mid)ans+=querysum(rt<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    int querymax(int rt,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return tr[rt].mx;
        int mid=(l+r)>>1,ans=-inf;
        if(ql<=mid)ans=max(ans,querymax(rt<<1,l,mid,ql,qr));
        if(qr>mid)ans=max(ans,querymax(rt<<1|1,mid+1,r,ql,qr));
        return ans;
    }
    
    int qsum(int x,int y){
        int ans=0;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            ans+=querysum(1,1,n,tpos[top[x]],tpos[x]);
            x=dad[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        ans+=querysum(1,1,n,tpos[x],tpos[y]);
        return ans;
    }
    int qmax(int x,int y){
        int ans=-inf;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            ans=max(ans,querymax(1,1,n,tpos[top[x]],tpos[x]));
            x=dad[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        ans=max(ans,querymax(1,1,n,tpos[x],tpos[y]));
        return ans;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        dfs(1);dfs_(1);build(1,1,n);
        scanf("%d",&q);
        for(;q;q--){
            int x,y;char s[10];
            scanf("%s%d%d",s,&x,&y);
            if(s[1]=='H')update(1,1,n,tpos[x],y);
            if(s[1]=='M')printf("%d
    ",qmax(x,y));
            if(s[1]=='S')printf("%d
    ",qsum(x,y));
        }
        return 0;
    }
    AC

    T4BZOJ4034树上操作

    传送门

    题目大意:区间修改 子树和 节点到根节点的路径权值和

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 500005
    #define LL long long
    using namespace std;
    
    int sumedge,cnt,n,m;
    int head[maxn],size[maxn],dad[maxn],deep[maxn],top[maxn];
    int tpos[maxn],re[maxn],w[maxn];
    
    struct Tree{
        int l,r;LL sum,s;
    }tr[maxn<<2];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<1];
    
    
    void read(int &x){
        char ch=getchar();x=0;int f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        x=x*f;
    }
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;dfs(v);
            size[x]+=size[v];
        }
    }
    
    void dfs_(int x){
        int s=0;tpos[x]=++cnt;re[cnt]=x;
        if(!top[x])top[x]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs_(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=s)dfs_(v);
        }
    }
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
        return;
    }
    
    void pushdown(int rt){
        if(!tr[rt].s)return;
        tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s;
        tr[rt<<1].sum+=(LL)(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s;
        tr[rt<<1|1].sum+=(LL)(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s;
        tr[rt].s=0;return;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].sum=w[re[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void change(int rt,int l,int r,int ql,int qr,int p){
        if(l>=ql&&r<=qr){
            tr[rt].sum+=(LL)(r-l+1)*p;
            tr[rt].s+=p;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr,p);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p);
        pushup(rt);
    }
    
    LL query_sum(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr){
            return tr[rt].sum;
        }
        pushdown(rt);
        int mid=(l+r)>>1;LL ans=0;
        if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr);
        if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    LL query(int x){
        LL ret=0;
        for(;top[x]!=1;){
            ret+=query_sum(1,1,n,tpos[top[x]],tpos[x]);
            x=dad[top[x]];
        }
        ret+=query_sum(1,1,n,1,tpos[x]);
        return ret;
    }
    
    int main(){
        read(n);read(m);
        for(int i=1;i<=n;i++)read(w[i]);
        for(int i=1;i<n;i++){
            int x,y;
            read(x);read(y);
            add(x,y);add(y,x);
        }
        dfs(1);dfs_(1);build(1,1,n);
        for(int i=1;i<=m;i++){
            int od,x,a;
            read(od);read(x);
            if(od==1){
                read(a);
                change(1,1,n,tpos[x],tpos[x],a);
            }else if(od==2){
                read(a);
                change(1,1,n,tpos[x],tpos[x]+size[x]-1,a);
            }else if(od==3){
                printf("%lld
    ",query(x));
            }
        }
        return 0;
    }
    
    AC
    AC

    T5BZOJ2243染色

    传送门

    题目大意:求a-b路径上有多少个颜色连续的序列

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100009
    using namespace std;
    
    int n,m,cnt,sumedge;
    int head[maxn],dad[maxn],size[maxn],deep[maxn],top[maxn];
    int c[maxn],re[maxn],tpos[maxn];
    char s[10];
    
    struct Tree{
        int l,r,sum,lc,rc,s;
    }tr[maxn<<2];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;dfs(v);
            size[x]+=size[v];
        }
    }
    
    void dfs_(int x){
        int s=0;tpos[x]=++cnt;re[cnt]=x;
        if(!top[x])top[x]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs_(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=s)dfs_(v);
        }
    }
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum-(tr[rt<<1].rc==tr[rt<<1|1].lc);
        tr[rt].lc=tr[rt<<1].lc;tr[rt].rc=tr[rt<<1|1].rc;
        return;
    }
    
    void pushdown(int rt){
        if(!tr[rt].s)return;
        tr[rt<<1].sum=tr[rt<<1|1].sum=1;
        tr[rt<<1].rc=tr[rt<<1].lc=tr[rt<<1|1].lc=tr[rt<<1|1].rc=tr[rt].s;
        tr[rt<<1].s=tr[rt<<1|1].s=tr[rt].s;
        tr[rt].s=0;return;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].sum=1;tr[rt].lc=tr[rt].rc=c[re[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void change(int rt,int l,int r,int ql,int qr,int p){
        if(l>=ql&&r<=qr){
            tr[rt].sum=1;tr[rt].lc=tr[rt].rc=p;tr[rt].s=p;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr,p);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p);
        pushup(rt);
    }
    
    int query_sum(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr){
            return tr[rt].sum;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(qr<=mid)return query_sum(rt<<1,l,mid,ql,qr);
        if(ql>mid)return query_sum(rt<<1|1,mid+1,r,ql,qr);
        return query_sum(rt<<1,l,mid,ql,qr)+query_sum(rt<<1|1,mid+1,r,ql,qr)-(tr[rt<<1].rc==tr[rt<<1|1].lc);//**
    }
    
    int getcolr(int rt,int l,int r,int p){
        if(l==r)return tr[rt].lc;
        pushdown(rt);
        int mid=(l+r)>>1;
        if(p<=mid)return getcolr(rt<<1,l,mid,p);
        if(p>mid)return getcolr(rt<<1|1,mid+1,r,p);
    }
    
    int query(int x,int y){
        int ret=0;
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            ret+=query_sum(1,1,n,tpos[top[y]],tpos[y]);
            if(getcolr(1,1,n,tpos[top[y]])==getcolr(1,1,n,tpos[dad[top[y]]]))ret--;
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        ret+=query_sum(1,1,n,tpos[x],tpos[y]);
        return ret;
    }
    
    void change_(int x,int y,int c){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            change(1,1,n,tpos[top[y]],tpos[y],c);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        change(1,1,n,tpos[x],tpos[y],c);
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&c[i]);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        dfs(1);dfs_(1);build(1,1,n);
        for(int i=1;i<=m;i++){
            int x,y,z;
            scanf("%s",s);
            if(s[0]=='Q'){
                scanf("%d%d",&x,&y);
                printf("%d
    ",query(x,y));
            }else  {
                scanf("%d%d%d",&x,&y,&z);
                change_(x,y,z);
            }
        }
        return 0;
    }
    
    AC
    AC

    T6BZOJ1984月下毛景树

    题目大意:

    Max x--y 树上x--y之间边的最大权值

    Cover x--y w.树上x--y之前边的权值都变为w

    Add x--y w 树上x--y之间边权都加w

    Change x w把第x条边权值改为w

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 300009
    using namespace std;
    
    int n,m,cnt,sumedge;
    int size[maxn],dad[maxn],deep[maxn],top[maxn],head[maxn];
    int tpos[maxn],re[maxn],fe[maxn],st[maxn],ed[maxn];
    char s[10];
    
    struct Tree{
        int l,r,mx,adc,cvs;
    }tr[maxn<<2];
    
    struct Edge{
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y,int z){
        edge[++sumedge]=Edge(x,y,z,head[x]);
        head[x]=sumedge;
    }
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;fe[v]=edge[i].z;dfs(v);
            size[x]+=size[v];
        }
    }
    
    void dfs_(int x){
        int s=0;
        if(!top[x])top[x]=x;
        tpos[x]=++cnt;re[cnt]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs_(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=s)dfs_(v);
        }
    }
    
    void pushup(int rt){
        tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx);
        return;
    }
    
    void pushdown(int rt){
        if(tr[rt].cvs!=-1){
            tr[rt<<1].mx=tr[rt<<1|1].mx=tr[rt].cvs;
            tr[rt<<1].adc=tr[rt<<1|1].adc=0;
            tr[rt<<1].cvs=tr[rt<<1|1].cvs=tr[rt].cvs;
            tr[rt].cvs=-1;
        }
        if(tr[rt].adc){
            tr[rt<<1].mx+=tr[rt].adc;tr[rt<<1|1].mx+=tr[rt].adc;
            tr[rt<<1].adc+=tr[rt].adc;tr[rt<<1|1].adc+=tr[rt].adc;
            tr[rt].adc=0;
        }
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;tr[rt].cvs=-1;
        if(l==r){
            tr[rt].mx=fe[re[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    //-----------------------------------------------------
    void change_Node(int rt,int l,int r,int p,int w){
        if(l==r){
            tr[rt].mx=w;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(p<=mid)change_Node(rt<<1,l,mid,p,w);
        if(p>mid)change_Node(rt<<1|1,mid+1,r,p,w);
        pushup(rt);
    }
    
    void change_node(int k,int w){
        int p,x,y;
        x=st[k];y=ed[k];p=dad[x]==y?x:y;
        change_Node(1,1,n,tpos[p],w);
    }
    //--------------------------------------------------------
    void change_Cover(int rt,int l,int r,int ql,int qr,int w){
        if(l>=ql&&r<=qr){
            tr[rt].mx=w;tr[rt].cvs=w;tr[rt].adc=0;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change_Cover(rt<<1,l,mid,ql,qr,w);
        if(qr>mid)change_Cover(rt<<1|1,mid+1,r,ql,qr,w);
        pushup(rt);
    }
    
    void change_cover(int x,int y,int w){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            change_Cover(1,1,n,tpos[top[y]],tpos[y],w);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        change_Cover(1,1,n,tpos[x]+1,tpos[y],w);
    }
    //---------------------------------------------------------
    void change_Add(int rt,int l,int r,int ql,int qr,int w){
        if(l>=ql&&r<=qr){
            tr[rt].mx+=w;tr[rt].adc+=w;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change_Add(rt<<1,l,mid,ql,qr,w);
        if(qr>mid)change_Add(rt<<1|1,mid+1,r,ql,qr,w);
        pushup(rt);
    }
    
    void change_add(int x,int y,int w){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            change_Add(1,1,n,tpos[top[y]],tpos[y],w);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        change_Add(1,1,n,tpos[x]+1,tpos[y],w);
    }
    //-----------------------------------------------------------
    int query_mx(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr){
            return tr[rt].mx;
        }
        pushdown(rt);
        int mid=(l+r)>>1,ret=-1;
        if(ql<=mid)ret=max(ret,query_mx(rt<<1,l,mid,ql,qr));
        if(qr>mid)ret=max(ret,query_mx(rt<<1|1,mid+1,r,ql,qr));
        return ret;
    }
    
    int query(int x,int y){
        int ans=-1;
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            ans=max(ans,query_mx(1,1,n,tpos[top[y]],tpos[y]));
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        ans=max(ans,query_mx(1,1,n,tpos[x]+1,tpos[y]));
        return ans;
    }
    //------------------------------------------------------------
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int z;
            scanf("%d%d%d",&st[i],&ed[i],&z);
            add(st[i],ed[i],z);add(ed[i],st[i],z);
        }
        dfs(1);dfs_(1);build(1,1,n);
        while(1){
            int x,y,z;
            scanf("%s",s);
            if(s[0]=='S')break;
            if(s[1]=='h'){
                scanf("%d%d",&x,&z);                                                            
                change_node(x,z);
            }else if(s[1]=='o'){
                scanf("%d%d%d",&x,&y,&z);
                change_cover(x,y,z);
            }else if(s[1]=='d'){
                scanf("%d%d%d",&x,&y,&z);
                change_add(x,y,z);
            }else if(s[2]=='x'){
                scanf("%d%d",&x,&y);
                printf("%d
    ",query(x,y));
            }
        }
        return 0;
    }
    
    AC
    AC
  • 相关阅读:
    【数位dp】Beautiful Numbers @2018acm上海大都会赛J
    【状压dp】Trie 树 @中山纪念中学20170304
    两个给点染色的问题-树上染色与图上染色
    【贪心】经营与开发 @upc_exam_5500
    【二分+拓扑排序】Milking Order @USACO 2018 US Open Contest, Gold/upc_exam_6348
    【并查集】Connectivity @ABC049&amp;ARC065/upcexam6492
    【倍增】T-shirt @2018acm徐州邀请赛 I
    Sparse Coding: Autoencoder Interpretation
    Sparse Coding
    Pooling
  • 原文地址:https://www.cnblogs.com/zzyh/p/7704060.html
Copyright © 2020-2023  润新知