• P3313-[SDOI2014]旅行【树链剖分,线段树】


    正题

    题目链接:https://www.luogu.com.cn/problem/P3313


    题目大意

    (n)个点的一棵树,每个点有一个颜色和权值,有操作

    1. 修改一个点的权值
    2. 修改一个点的颜色
    3. 询问一条路径的某颜色的权值和
    4. 询问一条路径的某颜色的权值最大值

    解题思路

    询问路径直接树剖先,然后对于每个颜色开一个动态开点的线段树,单点修改所以不会炸空间。

    然后就是树链剖分的板子了。

    时间复杂度(O(nlog^2n ))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+10;
    struct node{
        int to,next;
    }a[N<<1];
    int n,q,cnt,tot,w[N],c[N],ls[N],rt[N];
    int fa[N],dep[N],siz[N],top[N],son[N],rfn[N];
    struct SegTree{
        int cnt,w[N<<6],v[N<<6],ls[N<<6],rs[N<<6];
        void Change(int &x,int L,int R,int pos,int val){
            if(!x)x=++cnt;
            if(L==R){w[x]+=val;v[x]+=val;return;}
            int mid=(L+R)>>1;
            if(pos<=mid)Change(ls[x],L,mid,pos,val);
            else Change(rs[x],mid+1,R,pos,val);
            v[x]=max(v[ls[x]],v[rs[x]]);
            w[x]=w[ls[x]]+w[rs[x]];
            return;
        }
        int Ask(int x,int L,int R,int l,int r){
            if(!x)return 0;
            if(L==l&&R==r)return w[x];
            int mid=(L+R)>>1;
            if(r<=mid)return Ask(ls[x],L,mid,l,r);
            if(l>mid)return Ask(rs[x],mid+1,R,l,r);
            return Ask(ls[x],L,mid,l,mid)+Ask(rs[x],mid+1,R,mid+1,r);
        }
        int Query(int x,int L,int R,int l,int r){
            if(!x)return 0;
            if(L==l&&R==r)return v[x];
            int mid=(L+R)>>1;
            if(r<=mid)return Query(ls[x],L,mid,l,r);
            if(l>mid)return Query(rs[x],mid+1,R,l,r);
            return max(Query(ls[x],L,mid,l,mid),Query(rs[x],mid+1,R,mid+1,r));
        }
    }T;
    void addl(int x,int y){
        a[++tot].to=y;
        a[tot].next=ls[x];
        ls[x]=tot;return;
    }
    void dfs1(int x){
        siz[x]=1;dep[x]=dep[fa[x]]+1;
        for(int i=ls[x];i;i=a[i].next){
            int y=a[i].to;
            if(y==fa[x])continue;
            fa[y]=x;dfs1(y);
            siz[x]+=siz[y];
            if(siz[y]>siz[son[x]])son[x]=y;
        }
        return;
    }
    void dfs2(int x){
        rfn[x]=++cnt;
        T.Change(rt[c[x]],1,n,cnt,w[x]);
        if(son[x]){
            top[son[x]]=top[x];
            dfs2(son[x]);
        }
        for(int i=ls[x];i;i=a[i].next){
            int y=a[i].to;
            if(y==fa[x]||y==son[x])continue;
            top[y]=y;dfs2(y);
        }
        return;
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&w[i],&c[i]);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            addl(x,y);addl(y,x);
        }
        dfs1(1);top[1]=1;dfs2(1);
        while(q--){
            char op[3];int x,y;
            scanf("%s%d%d",op,&x,&y);
            if(op[0]=='C'&&op[1]=='C'){
                T.Change(rt[c[x]],1,n,rfn[x],-w[x]);
                T.Change(rt[y],1,n,rfn[x],w[x]);
                c[x]=y;
            }
            else if(op[0]=='C'&&op[1]=='W'){
                T.Change(rt[c[x]],1,n,rfn[x],y-w[x]);
                w[x]=y;
            }
            else if(op[0]=='Q'&&op[1]=='S'){
                int z=c[x],ans=0;
                while(top[x]!=top[y]){
                    if(dep[top[x]]<dep[top[y]])swap(x,y);
                    ans+=T.Ask(rt[z],1,n,rfn[top[x]],rfn[x]);
                    x=fa[top[x]];
                }
                if(dep[x]>dep[y])swap(x,y);
                ans+=T.Ask(rt[z],1,n,rfn[x],rfn[y]);
                printf("%d
    ",ans);
            }
            else if(op[0]=='Q'&&op[1]=='M'){
                int z=c[x],ans=0;
                while(top[x]!=top[y]){
                    if(dep[top[x]]<dep[top[y]])swap(x,y);
                    ans=max(ans,T.Query(rt[z],1,n,rfn[top[x]],rfn[x]));
                    x=fa[top[x]];
                }
                if(dep[x]>dep[y])swap(x,y);
                ans=max(ans,T.Query(rt[z],1,n,rfn[x],rfn[y]));
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    用户控件赋值
    计算一串数字中每个数字出现的次数
    如何理解c和c++的复杂类型声明
    STM32 NVIC学习
    stm32f10x_flash.c中文版
    IBM中国研究院Offer之感言——能力是一种态度
    对于STM32别名区的理解 (转载)
    STM32时钟学习之STM3210X_RCC.H解读
    STM32 DMA
    STM32 内部时钟输出PA.8(MCO)
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14296620.html
Copyright © 2020-2023  润新知