zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    求概率 Bag of mice CodeForces
    HDU 3853 LOOPS(概率DP)
    HDU 4405 Aeroplane chess (概率DP & 期望)
    求期望 ZOJ 3329 One Person Game
    poj 3774 Scout YYF I (矩阵优化的概率DP)
    codeforces 600D Area of Two Circles' Intersection
    codeforces 600A Extract Numbers
    codeforces 600C Make Palindrome
    POJ
    POJ
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8580570.html
Copyright © 2011-2022 走看看