[SDOI2014]旅行

题解:

这题一看就知道要么是树剖要么是lct

仔细分析一下

要是对每个颜色维护一下

插入和删除就相当于对一个的权值进行改变(删除就是变成0)

问题是空间不够了

那就树剖搞动态开点 问题就解决了

对于lct,可以把颜色分开来离线搞

但是对于这道题显然树剖比较有优势

因为lct细节挺多的。。

比如当一个点修改时会对后继这个点的所有颜色有影响要记录

复原的时候lct的树不用动他就把修改过的那些权值赋0就好了(拿队列记录一下)

以后有空再写lct的

下面是树剖的代码

太久没写过主席树调出好多错

 

#include <bits/stdc++.h>
using namespace std;
const int N=2e6+100;
int fa[N],son[N],dep[N],size[N],root[N],head[N];
int c[N],w[N],id[N],real2[N],num,l,top[N];
int leftson[N],rightson[N],cnt,n,m;
struct re{
    int a,b;
}a[N*2];
void arr(int x,int y)
{
    a[++l].a=head[x];
    a[l].b=y;
    head[x]=l;
}
void dfs1(int x,int y)
{
    fa[x]=y; dep[x]=dep[y]+1;
    son[x]=-1; size[x]=1;
    int u=head[x];
    while (u)
    {
        int v=a[u].b;
        if (v!=y)
        {
            dfs1(v,x);
            size[x]+=size[v];
            if (size[son[x]]<size[v])
              son[x]=v;
        }
        u=a[u].a;
    }
}
void dfs2(int x,int y)
{
    top[x]=y; num++;
    id[x]=num; real2[num]=x;
    if (son[x]==-1) return;
    dfs2(son[x],y);
    int u=head[x];
    while (u)
    {
        int v=a[u].b;
        if (v!=fa[x]&&v!=son[x])
          dfs2(v,v);
        u=a[u].a;    
    }
}
struct ree{
    int h,t,sum,maxn;
}p[10000000];
#define mid (h+t)/2
void updata(int x)
{
    p[x].sum=p[leftson[x]].sum+p[rightson[x]].sum;
    p[x].maxn=max(p[leftson[x]].maxn,p[rightson[x]].maxn);
}
void change(int &x,int h,int t,int pos,int w)
{
    if (x==0) x=++cnt;
    if (h==t)
    {
        p[x].sum=w; p[x].maxn=w; return;
    }
    if (pos<=mid) change(leftson[x],h,mid,pos,w);
    else change(rightson[x],mid+1,t,pos,w);
    updata(x);
}
int query1(int x,int h,int t,int posh,int post)
{
    if (x==0||posh>t||post<h) return(0);
    if (posh<=h&&t<=post)
    {
        return(p[x].sum);
    }
    return(query1(leftson[x],h,mid,posh,post)+query1(rightson[x],mid+1,t,posh,post));
}
int query2(int x,int h,int t,int posh,int post)
{
    if (x==0||posh>t||post<h) return(0);
    if (posh<=h&&t<=post)
    {
        return(p[x].maxn);
    }
    return(max(query2(leftson[x],h,mid,posh,post),query2(rightson[x],mid+1,t,posh,post)));
}
int query1x(int col,int x,int y)
{
    int ans=0,f1=top[x],f2=top[y];
    while (f1!=f2)
    {
        if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        ans+=query1(root[col],1,n,id[f1],id[x]);
        x=fa[f1]; f1=top[x];
    }
    if (dep[x]<dep[y]) swap(x,y);
    ans+=query1(root[col],1,n,id[y],id[x]);
    return(ans);
}
int query2x(int col,int x,int y)
{
    int ans=0,f1=top[x],f2=top[y];
    while (f1!=f2)
    {
        if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        ans=max(ans,query2(root[col],1,n,id[f1],id[x]));
        x=fa[f1]; f1=top[x];
    }
    if (dep[x]<dep[y]) swap(x,y);
    ans=max(ans,query2(root[col],1,n,id[y],id[x]));
    return(ans);
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++)
      cin>>w[i]>>c[i];
    int cc,dd;
    for (int i=1;i<=n-1;i++)
    {
        cin>>cc>>dd;
        arr(cc,dd); arr(dd,cc);
    }
    dfs1(1,0);
    dfs2(1,1);
    for (int i=1;i<=n;i++)
      change(root[c[i]],1,n,id[i],w[i]);
    for (int i=1;i<=m;i++)
    {
        char cc0,cc1;
        int x,y;
        cin>>cc0>>cc1>>x>>y;
        if (cc0=='Q'&&cc1=='S')
        {
            cout<<query1x(c[x],x,y)<<endl;
        }
        if (cc0=='C'&&cc1=='W')
        {
            w[x]=y;
            change(root[c[x]],1,n,id[x],y);
        }  
        if (cc0=='C'&&cc1=='C')
        {
            change(root[c[x]],1,n,id[x],0);
            c[x]=y;
            change(root[y],1,n,id[x],w[x]);
        }
        if (cc0=='Q'&&cc1=='M')
        {
            cout<<query2x(c[x],x,y)<<endl;
        }
    }
    return 0;
}

 

posted @ 2018-03-16 13:29  尹吴潇  阅读(171)  评论(0编辑  收藏  举报