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;
    }
  • 相关阅读:
    Linux 共享库
    使用Visual Studio(VS)开发Qt程序代码提示功能的实现(转)
    ZOJ 3469 Food Delivery(区间DP)
    POJ 2955 Brackets (区间DP)
    HDU 3555 Bomb(数位DP)
    HDU 2089 不要62(数位DP)
    UESTC 1307 windy数(数位DP)
    HDU 4352 XHXJ's LIS(数位DP)
    POJ 3252 Round Numbers(数位DP)
    HDU 2476 String painter (区间DP)
  • 原文地址:https://www.cnblogs.com/Narh/p/9419613.html
Copyright © 2011-2022 走看看