• P3313 [SDOI2014]旅行(动态开点线段树+树链剖分)


    这题如果直接做,显然是是对每个信仰维护一棵线段树,但是这样铁定炸内存,因此考虑使用动态开点线段树

    这样的答案就和询问的个数相关。之后就是普通的树链剖分维护

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pll;
    const int N=2e5+10;
    const int M=2e6+10;
    const int inf=0x3f3f3f3f;
    const ll mod=998244353;
    int id[N],w[N],dfn[N],top[N],h[N],e[N],ne[N],idx,times;
    int fa[N],sz[N],son[N],depth[N],rt[N];
    int c[N];
    int tot,n;
    ll ans;
    struct node{
        int l,r;
        int sum;
        int mx;
    }tr[N*24];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void dfs(int u){//算父亲和重儿子
        int i;
        sz[u]=1;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa[u])
                continue;
            fa[j]=u;
            depth[j]=depth[u]+1;
            dfs(j);
            sz[u]+=sz[j];
            if(sz[j]>sz[son[u]]){
                son[u]=j;
            }
        }
    }
    void dfs1(int u,int x){
        dfn[u]=++times;
        id[times]=u;
        top[u]=x;
        if(!son[u])
            return ;
        dfs1(son[u],x);
        for(int i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==son[u]||j==fa[u])
                continue;
            dfs1(j,j);
        }
    }
    void pushup(int u){
        int l=tr[u].l,r=tr[u].r;
        tr[u].mx=max(tr[l].mx,tr[r].mx);
        tr[u].sum=tr[l].sum+tr[r].sum;
    }
    void pushdown(int u){
        tr[u].mx=tr[u].sum=0;
    }
    void modify(int &u,int x,int l,int r,int v){
        if(!u) u=++tot;
        if(l==r){
            tr[u].sum=tr[u].mx=v;
            return ;
        }
        int mid=l+r>>1;
        if(x<=mid) modify(tr[u].l,x,l,mid,v);
        else modify(tr[u].r,x,mid+1,r,v);
        pushup(u);
    }
    void del(int &u,int x,int l,int r){
        if(!u) return ;
        if(l==r){
            pushdown(u);
            u=0;
            return ;
        }
        int mid=l+r>>1;
        if(x<=mid) del(tr[u].l,x,l,mid);
        else del(tr[u].r,x,mid+1,r);
        pushup(u);
    }
    ll query_sum(int &u,int L,int R,int l,int r){
        if(!u) return 0;
        if(L<=l&&r<=R){
            return tr[u].sum;
        }
        ll ans=0;
        int mid=l+r>>1;
        if(L<=mid) ans+=query_sum(tr[u].l,L,R,l,mid);
        if(R>mid) ans+=query_sum(tr[u].r,L,R,mid+1,r);
        return ans;
    }
    ll query_mx(int &u,int L,int R,int l,int r){
        if(!u) return 0;
        if(L<=l&&r<=R){
            return tr[u].mx;
        }
        ll ans=0;
        int mid=l+r>>1;
        if(L<=mid) ans=max(ans,query_mx(tr[u].l,L,R,l,mid));
        if(R>mid) ans=max(ans,query_mx(tr[u].r,L,R,mid+1,r));
        return ans;
    }
    int main(){
        ios::sync_with_stdio(false);
        int q;
        cin>>n>>q;
        int i;
        memset(h,-1,sizeof h);
        for(i=1;i<=n;i++)
            cin>>w[i]>>c[i];
        for(i=1;i<n;i++){
            int a,b;
            cin>>a>>b;
            add(a,b);
            add(b,a);
        }
        dfs(1);
        dfs1(1,1);
        for(i=1;i<=n;i++){
            modify(rt[c[id[i]]],i,1,n,w[id[i]]);
        }
        string s;
        while(q--){
            cin>>s;
            int x,y;
            if(s[1]=='C'){
                cin>>x>>y;
                del(rt[c[x]],dfn[x],1,n);
                c[x]=y;
                modify(rt[c[x]],dfn[x],1,n,w[x]);
            }
            if(s[1]=='W'){
                cin>>x>>y;
                del(rt[c[x]],dfn[x],1,n);
                w[x]=y;
                modify(rt[c[x]],dfn[x],1,n,w[x]);
            }
            if(s[1]=='S'){
                cin>>x>>y;
                int k=c[x];
                ans=0;
                while(top[x]!=top[y]){
                    if(depth[top[x]]<depth[top[y]])
                        swap(x,y);
                    ans+=query_sum(rt[k],dfn[top[x]],dfn[x],1,n);
                    x=fa[top[x]];
                }
                if(depth[x]>depth[y])
                    swap(x,y);
                ans+=query_sum(rt[k],dfn[x],dfn[y],1,n);
                cout<<ans<<endl;
            }
            if(s[1]=='M'){
                cin>>x>>y;
                int k=c[x];
                ans=0;
                while(top[x]!=top[y]){
                    if(depth[top[x]]<depth[top[y]])
                        swap(x,y);
                    ans=max(ans,query_mx(rt[k],dfn[top[x]],dfn[x],1,n));
                    x=fa[top[x]];
                }
                if(depth[x]>depth[y])
                    swap(x,y);
                ans=max(ans,query_mx(rt[k],dfn[x],dfn[y],1,n));
                cout<<ans<<endl;
            }
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    路由器的配置
    逻辑卷
    valn配置
    交换分区和虚拟内存
    TCP和UDP
    语法练习1
    oracl通用函数
    AOP
    oracle查询操作
    Oracle中的转换函数
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13625946.html
Copyright © 2020-2023  润新知