• bzoj3531 树刨+线段树动态开点


    题意:一棵树,每个点有颜色,4种操作,1.单点修改权值 2.单点修改颜色 3.查询路径颜色相同的点权和 4.查询路径颜色相同的点权最大值。
    思路:树刨+线段树动态开点,开1e5个线段树。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;++i)
    #define for1(i,n) for(int i=1;i<=n;++i)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int maxn = 2e5+5;
    
    int a[maxn],b[maxn],head[maxn],deep[maxn],sz[maxn],par[maxn],son[maxn],p[maxn],fp[maxn],top[maxn],root[maxn];
    int n,q,tot = 1,id,cnt;
    class dsegment_tree{public:
        struct dsegment_node{
            int son[2],sum,maxv;
        }node[maxn*50];
        void update(int pos,int v,int &now,int l = 1,int r = n){
            if(!now) now = ++cnt;
            if(l==r){
                node[now].sum = node[now].maxv = v;
                return;
            }
            int mid = l+r>>1;
            if(pos<=mid) update(pos,v,node[now].son[0],l,mid);
            else update(pos,v,node[now].son[1],mid+1,r);
            node[now].sum = node[node[now].son[0]].sum+node[node[now].son[1]].sum;
            node[now].maxv = max(node[node[now].son[0]].maxv,node[node[now].son[1]].maxv);
        }
        int query(int L,int R,int now,int l = 1,int r = n){
            if(L<=l&&R>=r) return node[now].sum;
            int mid = l+r>>1,res = 0;
            if(L<=mid) res+=query(L,R,node[now].son[0],l,mid);
            if(R>mid) res+=query(L,R,node[now].son[1],mid+1,r);
            return res;
        }
        int query2(int L,int R,int now,int l = 1,int r = n){
            if(L<=l&&R>=r) return node[now].maxv;
            int mid = l+r>>1,res = 0;
            if(L<=mid) res = max(res,query2(L,R,node[now].son[0],l,mid));
            if(R>mid) res = max(res,query2(L,R,node[now].son[1],mid+1,r));
            return res;
        }
    }tree;
    struct edge{
        int v,nex;
    }e[maxn];
    void add(int u,int v){
        e[++tot] = {v,head[u]},head[u] = tot;
        e[++tot] = {u,head[v]},head[v] = tot;
    }
    void dfs(int u,int pre,int d){
        deep[u] = d,sz[u] = 1,par[u] = pre;
        for(int i = head[u];i;i = e[i].nex){
            int v = e[i].v;
            if(v==pre) continue;
            dfs(v,u,d+1);
            sz[u]+=sz[v];
            if(sz[son[u]]<sz[v]) son[u] = v;
        }
    }
    void getpos(int u,int gg){
        top[u] = gg,p[u] = ++id,fp[id] = u;
        if(son[u]) getpos(son[u],gg);
        for(int i = head[u];i;i = e[i].nex){
            int v = e[i].v;
            if(v==par[u]||v == son[u]) continue;
            getpos(v,v);
        }
    }
    int calsum(int x,int y){
        int z = b[x];
        int fx = top[x],fy = top[y];
        int res = 0;
        while(fx!=fy){
            if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y);
            res+=tree.query(p[fx],p[x],root[z]);
            x = par[fx],fx = top[x];
        }
        if(deep[x]>deep[y]) swap(x,y);
        res+=tree.query(p[x],p[y],root[z]);
        return res;
    }
    int calmax(int x,int y){
        int z = b[x];
        int fx = top[x],fy = top[y];
        int res = 0;
        while(fx!=fy){
            if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y);
            res = max(res,tree.query2(p[fx],p[x],root[z]));
            x = par[fx],fx = top[x];
        }
        if(deep[x]>deep[y]) swap(x,y);
        res= max(res,tree.query2(p[x],p[y],root[z]));
        return res;
    }
    int main(){
        IO;
        cin>>n>>q;
        for1(i,n) cin>>a[i]>>b[i];
        for1(i,n-1){
            int x,y;cin>>x>>y;
            add(x,y);
        }
        dfs(1,0,0);
        getpos(1,1);
        for1(i,n) tree.update(p[i],a[i],root[b[i]]);
        for1(i,q){
            string s;int x,y;cin>>s>>x>>y;
            if(s[1] == 'C'){
                tree.update(p[x],0,root[b[x]]);
                tree.update(p[x],a[x],root[y]);
                b[x] = y;
            }else if(s[1]=='W'){
                tree.update(p[x],y,root[b[x]]);
                a[x] = y;
            }else if(s[1]=='S') cout<<calsum(x,y)<<'
    ';
            else cout<<calmax(x,y)<<'
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    vue滑块拖拽校验
    vue和原生自动聚焦
    vue实现bar左右拖拽
    fastclick插件使用
    三大家族易忘点和案例
    移动端调试工具chrome+devtools
    restful 与 webapi 详解
    .NET Core 中依赖注入框架详解 Autofac
    .NET Core 对象( Transient、Scope、Singleton )生命周期详解 (对象创建以及释放)
    C# 通过DataSet 获取SQL 存储过程返回的多个结果集(tables)
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520281.html
Copyright © 2020-2023  润新知