luogu P3767 膜法

传送门

这题如果没有删除操作,可以直接使用可持久化并查集

注意到这种可持久化的依赖关系(是这样说的把)是一棵树,然后对于一个点,自己的操作会影响自己的那棵子树,并且如果是删除操作,就会使得一个子树没有加入操作.如果考虑了dfn序,那么每个操作影响的都是一个连续区间,一个删除操作会把一个加入操作的区间挖一个空

于是考虑线段树分治,把依赖关系的树建出来,以dfn序为下标建立线段树,每个点的加入操作都加到线段树的某个区间上去,然后从根出发,遇到一个点就做一遍操作,维护一下带权并查集,顺便把操作影响加入栈中,到叶子节点就可以记录答案,然后退出某个点可以从操作栈顶部依次撤销操作

#include<bits/stdc++.h>
#define LL long long
#define ldb long double
#define il inline
#define re register
#define ft first
#define sc second
#define mkpr make_pair

using namespace std;
const int N=1e5+10,inf=999999999;
il int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[N],nt[N],hd[N],tot;
il void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;}
struct node
{
    int x,y,z;
};
vector<node> s[N<<2];
bool an[N];
int n,m,a[N],b[N][2],dfn[N],pp[N],sz[N],ti=-1;
vector<pair<int,int> > op[N];
int ff[N],mm[N],di[N],w[N],st[N][3],tp;
il int findf(int x)
{
    if(ff[x]==x)return x;
    int an=findf(ff[x]);
    di[x]=di[ff[x]]+w[x];
    return an;
}
#define mid ((l+r)>>1)
void modif(int o,int l,int r,int ll,int rr,node x)
{
    if(ll<=l&&r<=rr) {s[o].push_back(x);return;}
    if(ll<=mid) modif(o<<1,l,mid,ll,rr,x);
    if(rr>mid) modif(o<<1|1,mid+1,r,ll,rr,x);
}
void quer(int o,int l,int r,bool p)
{
    int nn=s[o].size();
    bool np=p;
    for(int i=0;i<nn;++i)
    {
        ++tp;
        int x=findf(s[o][i].x),y=findf(s[o][i].y),z=s[o][i].z,xx=di[s[o][i].x],yy=di[s[o][i].y];
        if(x!=y)
        {
            z=xx-yy-z;
            if(mm[x]<mm[y]) swap(x,y),z=-z;
            st[tp][0]=y,st[tp][1]=x,st[tp][2]=mm[x];
            ff[y]=x,mm[x]+=mm[y],w[y]=z;
        }
        else
        {
            st[tp][0]=st[tp][1]=st[tp][2]=0;
            if(((xx-yy-z)%5+5)%5) np=0;
        }
    }
    if(l==r) an[pp[l]]=np;
    else quer(o<<1,l,mid,np),quer(o<<1|1,mid+1,r,np);
    while(nn--)
    {
        ff[st[tp][0]]=st[tp][0],di[st[tp][0]]=w[st[tp][0]]=0;
        mm[st[tp][1]]=st[tp][2];
        --tp;
    }
}
#undef mid
void dfs(int x)
{
    pp[dfn[x]=++ti]=x,sz[x]=1;
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
        dfs(y);
        sz[x]+=sz[y];
    }
    if(a[x]==3)
    {
        int xx=b[x][0];
        op[xx].push_back(mkpr(dfn[x]-1,dfn[x]+sz[x]));
    }
}

int main()
{
    n=rd(),m=rd();
    for(int i=1;i<=m;++i)
    {
        add(rd(),i);
        a[i]=rd();
        if(a[i]<3) b[i][0]=rd(),b[i][1]=rd();
        else b[i][0]=rd();
    }
    dfs(0);
    for(int i=1;i<=m;++i)
    {
        if(a[i]==3) continue;
        sort(op[i].begin(),op[i].end());
        int nn=op[i].size(),l=dfn[i];
        for(int j=0;j<nn;l=op[i][j].sc,++j)
        {
            if(op[i][j].ft<l) continue;
            if(l<=op[i][j].ft) modif(1,1,m,l,op[i][j].ft,(node){b[i][0],b[i][1],a[i]});
        }
        if(l<=dfn[i]+sz[i]-1) modif(1,1,m,l,dfn[i]+sz[i]-1,(node){b[i][0],b[i][1],a[i]});
    }
    for(int i=1;i<=n;++i) ff[i]=i,mm[i]=1;
    quer(1,1,m,1);
    for(int i=1;i<=m;++i) puts(an[i]?"excited":"naive");
    return 0;
}
posted @ 2019-02-20 14:48  ✡smy✡  阅读(140)  评论(0编辑  收藏  举报