zoukankan      html  css  js  c++  java
  • 洛谷 3398 仓鼠找sugar——树链剖分

    题目:https://www.luogu.org/problemnew/show/P3398

    原来只要把值记录成第几次就行了。

    别忘了while(top[a]!=top[b])之后还要走一步。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    int n,q,hd[N],xnt,nxt[N<<1],to[N<<1],tim,top[N],fa[N],siz[N],son[N],dep[N],rnk[N];
    int ls[N<<1],rs[N<<1],val[N<<1],laz[N<<1];
    int rdn()
    {
        int ret=0;char ch=getchar();
        while(ch>'9'||ch<'0')ch=getchar();
        while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar();
        return ret;
    }
    void add(int x,int y)
    {
        to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;
        to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;
    }
    void dfs(int cr,int f)
    {
        fa[cr]=f;dep[cr]=dep[f]+1;siz[cr]=1;
        for(int i=hd[cr],v;i;i=nxt[i])
            if((v=to[i])!=f)
            {
                dfs(v,cr);siz[cr]+=siz[v];
                if(siz[v]>siz[son[cr]])son[cr]=v;
            }
    }
    void dfs(int cr)
    {
        rnk[cr]=++tim;
        if(son[cr])top[son[cr]]=top[cr],dfs(son[cr]);
        for(int i=hd[cr],v;i;i=nxt[i])
            if((v=to[i])!=fa[cr]&&v!=son[cr])
            {top[v]=v;dfs(v);}
    }
    void build(int l,int r,int cr)
    {
        val[cr]=N;laz[cr]=N;
        if(l==r)return;int mid=l+r>>1;
        ls[cr]=++tim;build(l,mid,ls[cr]);
        rs[cr]=++tim;build(mid+1,r,rs[cr]);
    }
    void pshd(int cr)
    {
        if(laz[cr]==N)return;
        laz[ls[cr]]=laz[rs[cr]]=val[ls[cr]]=val[rs[cr]]=laz[cr];
        laz[cr]=N;
    }
    void pshp(int cr)
    {
        val[cr]=min(val[ls[cr]],val[rs[cr]]);
    }
    void mdfy(int l,int r,int cr,int L,int R,int w)
    {
    //    printf("mdfy L=%d R=%d l=%d r=%d val=%d w=%d
    ",L,R,l,r,val[cr],w);
        if(l>=L&&r<=R){val[cr]=laz[cr]=w;return;}
        int mid=l+r>>1;pshd(cr);
        if(L<=mid)mdfy(l,mid,ls[cr],L,R,w);
        if(mid<R)mdfy(mid+1,r,rs[cr],L,R,w);
        pshp(cr);
    }
    void mdfy(int a,int b,int w)
    {
        while(top[a]!=top[b])
        {
            if(dep[top[a]]>dep[top[b]])swap(a,b);
            mdfy(1,n,1,rnk[top[b]],rnk[b],w);b=fa[top[b]];
        }
        if(dep[a]>dep[b])swap(a,b);
        mdfy(1,n,1,rnk[a],rnk[b],w);
    }
    bool query(int l,int r,int cr,int L,int R)
    {
    //    printf("query L=%d R=%d l=%d r=%d val=%d laz=%d
    ",L,R,l,r,val[cr],laz[cr]);
        if(l>=L&&r<=R)return val[cr]==q;
        int mid=l+r>>1;pshd(cr);
        bool ret=0;
        if(L<=mid)ret|=query(l,mid,ls[cr],L,R);
        if(mid<R)ret|=query(mid+1,r,rs[cr],L,R);
        return ret;
    }
    bool query(int a,int b)
    {
        bool ret=0;
        while(top[a]!=top[b])
        {
            if(dep[top[a]]>dep[top[b]])swap(a,b);
            ret|=query(1,n,1,rnk[top[b]],rnk[b]);b=fa[top[b]];
        }
        if(dep[a]>dep[b])swap(a,b);
        ret|=query(1,n,1,rnk[a],rnk[b]);
        return ret;
    }
    int main()
    {
        n=rdn();q=rdn();int a,b,c,d;
        for(int i=1;i<n;i++)
        {
            a=rdn();b=rdn();add(a,b);
        }
        dfs(1,0);top[1]=1;dfs(1);
        tim=1;val[0]=N;build(1,n,1);
        while(q--)
        {
    //        printf("q=%d
    ",q);
            a=rdn();b=rdn();c=rdn();d=rdn();
            mdfy(a,b,q);
            if(query(c,d))puts("Y");else puts("N");
        }
        return 0;
    }
  • 相关阅读:
    问题解决——MFC Ribbon 添加图标
    SQL Server 2008 R2——分组取前几名
    问题解决——VC 断点 无效 一个可能情况?
    C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅳ部分
    C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅱ部分
    随手小代码——最大子数组 联机算法
    随手小代码——最大子数组 分治法
    C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅰ部分
    问题解决——关闭子进程
    随手小代码——插入排序
  • 原文地址:https://www.cnblogs.com/Narh/p/9419613.html
Copyright © 2011-2022 走看看