BZOJ 3531 旅行

Posted on 2016-10-21 08:43  ziliuziliu  阅读(94)  评论(0编辑  收藏  举报

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

#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\n",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;
}