• 【题解】Luogu P4679 [ZJOI2011]道馆之战


    原题传送门

    码农题树剖好题,口袋妖怪是个好玩的游戏

    这道题要用树链剖分,我博客里有对树链剖分的详细介绍

    下文左右就代表树的节点按dfs序后的左右,上、下分别表示每个节点的A、B区域

    考虑在链上的情况,在当前考虑的区间中,令dis[0][0]表示从左上走到右上的最长路,dis[0][1]表示从左上到右下,dis[1][0],dis[1][1]以此类推. 令maxx[0][0]表示从左上出发能走的最大距离,maxx[0][1]表示左下的,maxx[1][0]表示右上,maxx[1][1]表示右下.它们的合并比较简单.令当前区间为c,左半区间为a,右半区间为b,那么:

    	c.dis[0][0]=Max(-inf,Max(a.dis[0][0]+b.dis[0][0],a.dis[0][1]+b.dis[1][0]));
    	c.dis[0][1]=Max(-inf,Max(a.dis[0][0]+b.dis[0][1],a.dis[0][1]+b.dis[1][1]));
    	c.dis[1][0]=Max(-inf,Max(a.dis[1][1]+b.dis[1][0],a.dis[1][0]+b.dis[0][0]));
    	c.dis[1][1]=Max(-inf,Max(a.dis[1][1]+b.dis[1][1],a.dis[1][0]+b.dis[0][1]));
    	c.maxx[0][0]=Max(a.maxx[0][0],Max(a.dis[0][0]+b.maxx[0][0],a.dis[0][1]+b.maxx[0][1]));
    	c.maxx[0][1]=Max(a.maxx[0][1],Max(a.dis[1][0]+b.maxx[0][0],a.dis[1][1]+b.maxx[0][1]));
    	c.maxx[1][0]=Max(b.maxx[1][0],Max(b.dis[0][0]+a.maxx[1][0],b.dis[1][0]+a.maxx[1][1]));
    	c.maxx[1][1]=Max(b.maxx[1][1],Max(b.dis[0][1]+a.maxx[1][0],b.dis[1][1]+a.maxx[1][1]));
    

    在树上怎么办呢?每次询问的是两个点之间的路径,很显然,要用线段树+树链剖分. 如果询问的两个点分别是x,y,令lans表示x向上跳得到的答案,rans表示y向上跳得到的答案,最后要将lans取反再与rans合并,因为当两个点最后跳到一起时,它们的左端点对应左端点,右端点对应右端点,而我们要求左端点对应右端点,右端点对应左端点,所以要取反(这个珂以画个图理解一下子)

    #include <bits/stdc++.h>
    #define N 50005
    #define inf (1<<30)
    using namespace std;
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline void Swap(register int &a,register int &b)
    {
        a^=b^=a^=b;
    }
    inline int Max(register int x,register int y)
    {
        return x>y?x:y;
    }
    struct edge{
        int to,next;
    }eg[N<<1];
    int head[N],cnt=0;
    inline void add(register int u,register int v)
    {
        eg[++cnt]=(edge){v,head[u]};
        head[u]=cnt;
    }
    int n,m;
    int size[N],dep[N],fa[N],son[N];
    int tot=0,dl[N],id[N],top[N];
    int a[N][2]; 
    inline void dfs1(register int x,register int faa)
    {
        fa[x]=faa;
        size[x]=1;
        dep[x]=dep[faa]+1;
        for(register int i=head[x];i;i=eg[i].next)
        {
        	int v=eg[i].to;
        	if(v==faa)
        		continue;
        	dfs1(v,x);
        	size[x]+=size[v];
        	if(size[v]>size[son[x]])
        		son[x]=v;
        }
    }
    inline void dfs2(register int x,register int t)
    {
        dl[x]=++tot;
        id[tot]=x;
        top[x]=t;
        if(son[x])
            dfs2(son[x],t);
        for(register int i=head[x];i;i=eg[i].next)
        {
        	int v=eg[i].to;
        	if(v==fa[x]||v==son[x])
        		continue;
        	dfs2(v,v);
        }
    }
    struct node{
        int dis[2][2],maxx[2][2];
        inline void clear()
        {
            memset(dis,0,sizeof(dis));
            memset(maxx,0,sizeof(maxx));
        }
        inline bool emptyy()
        {
            if(!dis[0][0]&&!dis[0][1]&&!dis[1][0]&&!dis[1][1]&&!maxx[0][0]&&!maxx[0][1]&&!maxx[1][0]&&!maxx[1][1])
                return true;
            return false;
        }
    }e[N<<2];
    inline node pushup(register node a,register node b)
    {
        node c;
        if(a.emptyy())
            c=b;
        else if(b.emptyy())
            c=a;
        else
        {
            c.dis[0][0]=Max(-inf,Max(a.dis[0][0]+b.dis[0][0],a.dis[0][1]+b.dis[1][0]));
            c.dis[0][1]=Max(-inf,Max(a.dis[0][0]+b.dis[0][1],a.dis[0][1]+b.dis[1][1]));
            c.dis[1][0]=Max(-inf,Max(a.dis[1][1]+b.dis[1][0],a.dis[1][0]+b.dis[0][0]));
            c.dis[1][1]=Max(-inf,Max(a.dis[1][1]+b.dis[1][1],a.dis[1][0]+b.dis[0][1]));
            c.maxx[0][0]=Max(a.maxx[0][0],Max(a.dis[0][0]+b.maxx[0][0],a.dis[0][1]+b.maxx[0][1]));
            c.maxx[0][1]=Max(a.maxx[0][1],Max(a.dis[1][0]+b.maxx[0][0],a.dis[1][1]+b.maxx[0][1]));
            c.maxx[1][0]=Max(b.maxx[1][0],Max(b.dis[0][0]+a.maxx[1][0],b.dis[1][0]+a.maxx[1][1]));
            c.maxx[1][1]=Max(b.maxx[1][1],Max(b.dis[0][1]+a.maxx[1][0],b.dis[1][1]+a.maxx[1][1]));
        }
        return c;
    }
    inline void build(register int x,register int l,register int r)
    {
        if(l==r)
        {
            int p=a[id[l]][0],q=a[id[l]][1];
            if(p==1&&q==1)
            {
                e[x].dis[0][0]=e[x].dis[1][1]=1;
                e[x].dis[0][1]=e[x].dis[1][0]=2;
                e[x].maxx[0][0]=e[x].maxx[0][1]=e[x].maxx[1][0]=e[x].maxx[1][1]=2;
            }
            else if(p==1)
            {
                e[x].dis[0][0]=1;
                e[x].dis[0][1]=e[x].dis[1][0]=e[x].dis[1][1]=-inf;
                e[x].maxx[0][0]=e[x].maxx[1][0]=1;
                e[x].maxx[0][1]=e[x].maxx[1][1]=-inf;
            }
            else if(q==1)
            {
                e[x].dis[0][0]=e[x].dis[0][1]=e[x].dis[1][0]=-inf;
                e[x].dis[1][1]=1;
                e[x].maxx[0][0]=e[x].maxx[1][0]=-inf;
                e[x].maxx[0][1]=e[x].maxx[1][1]=1;
            }
            else
            {
                for(register int i=0;i<=1;++i)
                    for(register int j=0;j<=1;++j)
                        e[x].dis[i][j]=e[x].maxx[i][j]=-inf;
            }
            return;
        }
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        e[x]=pushup(e[x<<1],e[x<<1|1]);
    }
    inline void update(register int x,register int l,register int r,register int v,register int p,register int q)
    {
        if(l==r)
        {
            if(p==1&&q==1)
            {
                e[x].dis[0][0]=e[x].dis[1][1]=1;
                e[x].dis[0][1]=e[x].dis[1][0]=2;
                e[x].maxx[0][0]=e[x].maxx[0][1]=e[x].maxx[1][0]=e[x].maxx[1][1]=2;
            }
            else if(p==1)
            {
                e[x].dis[0][0]=1;
                e[x].dis[0][1]=e[x].dis[1][0]=e[x].dis[1][1]=-inf;
                e[x].maxx[0][0]=e[x].maxx[1][0]=1;
                e[x].maxx[0][1]=e[x].maxx[1][1]=-inf;
            }
            else if(q==1)
            {
                e[x].dis[0][0]=e[x].dis[0][1]=e[x].dis[1][0]=-inf;
                e[x].dis[1][1]=1;
                e[x].maxx[0][0]=e[x].maxx[1][0]=-inf;
                e[x].maxx[0][1]=e[x].maxx[1][1]=1;
            }
            else
            {
                for(register int i=0;i<=1;++i)
                    for(register int j=0;j<=1;++j)
                        e[x].dis[i][j]=e[x].maxx[i][j]=-inf;
            }
            return;
        }
        int mid=l+r>>1;
        if(v<=mid)
            update(x<<1,l,mid,v,p,q);
        else
            update(x<<1|1,mid+1,r,v,p,q);
        e[x]=pushup(e[x<<1],e[x<<1|1]);
    }
    inline node rev(register node a)
    {
        Swap(a.maxx[0][0],a.maxx[1][0]);
        Swap(a.maxx[0][1],a.maxx[1][1]);
        Swap(a.dis[0][1],a.dis[1][0]);
        return a;
    }
    inline node query(register int x,register int l,register int r,register int L,register int R)
    {
        if(l==L&&r==R)
            return e[x];
        int mid=l+r>>1;
        if(R<=mid)
            return query(x<<1,l,mid,L,R);
        else if(L>mid)
            return query(x<<1|1,mid+1,r,L,R);
        else
            return pushup(query(x<<1,l,mid,L,mid),query(x<<1|1,mid+1,r,mid+1,R));
    }
    inline int Query(register int x,register int y)
    {
        node lans,rans;
        lans.clear();
        rans.clear();
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])
            {
                rans=pushup(query(1,1,n,dl[top[y]],dl[y]),rans);
                y=fa[top[y]];
            }
            else
            {
                lans=pushup(query(1,1,n,dl[top[x]],dl[x]),lans);
                x=fa[top[x]];
            }
        }
        if(dep[x]>dep[y])
            lans=pushup(query(1,1,n,dl[y],dl[x]),lans);
        else
            rans=pushup(query(1,1,n,dl[x],dl[y]),rans);
        lans=pushup(rev(lans),rans);
        int res=Max(lans.maxx[0][0],lans.maxx[0][1]);
        return res<0?0:res;
    }
    int main()
    {
        n=read(),m=read();
        for(register int i=1;i<n;++i)
        {
            int u=read(),v=read();
            add(u,v),add(v,u);
        }
        dfs1(1,0);
        dfs2(1,1);
        for(register int i=1;i<=n;++i)
        {
            char ch[3];
            scanf("%s",ch);
            a[i][0]=(ch[0]=='.')?1:0;
            a[i][1]=(ch[1]=='.')?1:0;
        }
        build(1,1,n);
        while(m--)
        {
            char c=getchar();
            while(c!='C'&&c!='Q')
                c=getchar();
            if(c=='C')
            {
                int u=read();
                char s[3];
                scanf("%s",s);
                int p=(s[0]=='.')?1:0,q=(s[1]=='.')?1:0;
                update(1,1,n,dl[u],p,q);
            }
            else
            {
                int u=read(),v=read();
                write(Query(u,v)),puts("");
            }
        } 
        return 0;
    }
    
  • 相关阅读:
    CentOS linux系统搭建LAMP环境
    网站跳出率高的优化方案
    IT痴汉的工作现状24-Just for fun
    windows下远程连接ubantu
    Hibernate基础映射
    我院同学在2013年第四届“蓝桥杯”全国软件专业人才设计与创业大赛全国总决赛中获得佳绩
    Linux下打开串口设置
    zoj 3261 Connections in Galaxy War
    Android之startActivityForResult的使用
    当心Azure跨区域数据传输产生额外费用
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10211747.html
Copyright © 2020-2023  润新知