zoukankan      html  css  js  c++  java
  • BZOJ 3531 旅行

    线段树动态开点或者平衡树。卡常没卡过。。。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<ctime>
    #define maxn 500050
    #define maxv 500050
    #define maxe 200050
    using namespace std;
    int n,m,x,y,z,g[maxv],nume=0,fath[maxv],top[maxv],dis[maxv],size[maxv],son[maxv],times=0,fa[maxv];
    int root[maxv],c[maxn],val[maxn],w[maxn],mx[maxn],sum[maxn],tot,reg=0,tree[maxn][3],pre,sub;
    char type[4];
    struct edge
    {
        int v,nxt;
    }e[maxe];
    struct io_t{
        char op[1<<23];
        char* s;
        io_t():s(op){
            s[ fread(s,1,
            sizeof op,stdin) ] = 0;
        }
        void scan(char* q){
            while(*s<48)
                ++s;
            while(*s>32)
                *q++=*s++;
            *q=0;
        }
        int scan(){
            static int v,j;
            v=0,j=1;
            while(*s<48)
                j=*s++^45;
            do
                v=v*10+*s++-48;
            while(*s>32);
            return j?v:-v;
        }
    }io;
    #define read io.scan
    void addedge(int u,int v)
    {
        e[++nume].v=v;
        e[nume].nxt=g[u];
        g[u]=nume;
    }
    void get_info()
    {
        n=read();m=read();tot=n;
        for (int i=1;i<=n;i++) {val[i]=read();c[i]=read();reg=max(reg,c[i]);}
        for (int i=1;i<=100000;i++) {root[i]=++tot;tree[root[i]][2]=++tot;fath[tot]=root[i];w[tot]=n+1;}
        for (int i=1;i<=n-1;i++)
        {
            x=read();y=read();
            addedge(x,y);addedge(y,x);
        }
    }
    void dfs1(int x)
    {
        size[x]=1;son[x]=0;
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (v!=fa[x])
            {
                fa[v]=x;dis[v]=dis[x]+1;
                dfs1(v);
                size[x]+=size[v];
                if (size[v]>size[son[x]]) son[x]=v;
            }
        }
    }
    void dfs2(int x,int father)
    {
        top[x]=father;w[x]=++times;
        if (son[x]) dfs2(son[x],father);
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (v!=fa[x] && v!=son[x])
                dfs2(v,v);
        }
    }
    void tree_cut() {dfs1(1);dfs2(1,1);}
    void pushup(int now)
    {
        sum[now]=sum[tree[now][1]]+sum[tree[now][2]]+val[now];
        mx[now]=max(val[now],max(mx[tree[now][1]],mx[tree[now][2]]));
    }
    void insert(int &now,int father,int x)
    {
        if (!now)
        {
            now=x;fath[now]=father;tree[now][1]=tree[now][2]=0;
            sum[now]=mx[now]=val[now];
            return;
        }
        if (w[x]<w[now]) insert(tree[now][1],now,x);
        else insert(tree[now][2],now,x);
        pushup(now);
    }
    void rotate(int x,int &k)
    {
        int y=fath[x],z=fath[y],l,r;
        if (tree[y][1]==x) l=1;else l=2;r=3-l;
        if (y==k) k=x;
        else
        {
            if (tree[z][1]==y) tree[z][1]=x;
            else tree[z][2]=x;
        }
        fath[x]=z;fath[y]=x;fath[tree[x][r]]=y;
        tree[y][l]=tree[x][r];tree[x][r]=y;
        pushup(y);pushup(x);
    }
    void splay(int x,int &k)
    {
        while (x!=k)
        {
            int y=fath[x],z=fath[y];
            if (y!=k)
            {
                if ((tree[z][1]==y)^(tree[y][1]==x)) rotate(x,k);
                else rotate(y,k);
            }
            rotate(x,k);
        }
    }
    void build_tree()
    {
        for (int i=1;i<=n;i++)
        {
            insert(root[c[i]],0,i);
            splay(i,root[c[i]]);
        }
    }
    void get_pre(int now,int x)
    {
        if (!now) return;
        if (w[now]<x) {pre=now;get_pre(tree[now][2],x);}
        else get_pre(tree[now][1],x);
    }
    void get_sub(int now,int x)
    {
        if (!now) return;
        if (w[now]>x) {sub=now;get_sub(tree[now][1],x);}
        else get_sub(tree[now][2],x);
    }
    void delete_(int x)
    {
        get_pre(root[c[x]],w[x]);get_sub(root[c[x]],w[x]);
        splay(pre,root[c[x]]);splay(sub,tree[root[c[x]]][2]);
        int now=tree[root[c[x]]][2];
        tree[now][1]=fath[x]=tree[x][1]=tree[x][2]=0;pushup(now);pushup(root[c[x]]);
    }
    int ask(int c,int l,int r,int type)
    {
        get_pre(root[c],l);get_sub(root[c],r);
        splay(pre,root[c]);
        splay(sub,tree[root[c]][2]);
        int now=tree[tree[root[c]][2]][1];
        if (type==1) return sum[now];
        else return mx[now];
    }
    void get_ans(int x,int y,int type,int c)
    {
        int ans=0;
        int f1=top[x],f2=top[y];
        while (f1!=f2)
        {
            if (dis[f1]<dis[f2]) {swap(f1,f2);swap(x,y);}
            if (type==1) ans+=ask(c,w[f1],w[x],1);
            else ans=max(ans,ask(c,w[f1],w[x],2));
            x=fa[f1];f1=top[x];
        }
        if (dis[x]>dis[y]) swap(x,y);
        if (type==1) ans+=ask(c,w[x],w[y],1);
        else ans=max(ans,ask(c,w[x],w[y],2));
        printf("%d
    ",ans);
    }
    void work()
    {
        for (int i=1;i<=m;i++)
        {
            read( type );
            if ((type[0]=='C') && (type[1]=='C'))
            {
                x=read();y=read();
                delete_(x);c[x]=y;
                insert(root[c[x]],0,x);
                splay(x,root[c[x]]);    
            }
            else if ((type[0]=='C') && (type[1]=='W'))
            {
                x=read();y=read();
                splay(x,root[c[x]]);val[x]=y;pushup(x);
            }
            else if ((type[0]=='Q') && (type[1]=='S')) {x=read();y=read();get_ans(x,y,1,c[y]);}
            else {x=read();y=read();get_ans(x,y,2,c[y]);}
        }
    }
    int main()
    {
        get_info();
        tree_cut();
        build_tree();
        work();
        return 0;
    }
  • 相关阅读:
    linux的ip配置
    脚本抓取mongoDB慢查询进程,生成kill语句,快速恢复mongodb CPU打满情况
    python脚本生成sql分库分表语句
    脚本获取rds慢日志
    问题反馈小平台实现 ----python练习
    python脚本 监控MySQL slave 状态
    传统复制的复制结构之间转换
    python判断合法IP并区分内网和外网地址
    ELK单台日志收集系统的搭建
    网站程序文件增量更新脚本
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5983327.html
Copyright © 2011-2022 走看看