INFOJ上60pts,但是我记得有一些特殊性质。
这个代码在完全随机的复杂度下是正确的,但是如果刻意卡的话会T飞
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#define N 1014514
#define lc p<<1
#define rc p<<1|1
using namespace std;
int n,m,q;
int head[N],to[N],nxt[N],tot;
int out[N],mn,ps;
set<int>st[N];
struct Segment_tree{
int l,r,v,mx,mn;
}t[4*N];
void pushup(int p){
t[p].mx=max(t[lc].mx,t[rc].mx);
t[p].mn=min(t[lc].mn,t[rc].mn);
}
void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
if(l==r){
t[p].mx=t[p].mn=t[p].v=0;
return;
}
build(lc,l,(l+r)/2);
build(rc,(l+r)/2+1,r);
pushup(p);
}
void change(int p,int x,int v){
if(t[p].l>x||t[p].r<x)return;
if(t[p].l==x&&t[p].r==x){
t[p].mn+=v;
t[p].mx+=v;
return;
}
change(lc,x,v);
change(rc,x,v);
pushup(p);
}
int qmin(int p,int l,int r){
if(t[p].l>r||t[p].r<l)return 1e9;
if(t[p].l>=l&&t[p].r<=r)return t[p].mn;
return min(qmin(lc,l,r),qmin(rc,l,r));
}
int qmax(int p,int l,int r){
if(t[p].l>r||t[p].r<l)return -1e9;
if(t[p].l>=l&&t[p].r<=r)return t[p].mx;
return max(qmax(lc,l,r),qmax(rc,l,r));
}
void add(int u,int v){
to[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
change(1,v,1);
out[v]++;
}
signed main(){
freopen("galaxy.in","r",stdin);
freopen("galaxy.out","w",stdout);
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
add(b,a);
st[b].insert(a);
}
scanf("%d",&q);
while(q--){
int op,u,v;
scanf("%d",&op);
if(op==1){
scanf("%d%d",&u,&v);
out[u]--;
change(1,u,-1);
//printf("ot:%d\n",out[u]);
st[v].erase(u);
}else if(op==2){
scanf("%d",&u);
for(set<int>::iterator it=st[u].begin();it!=st[u].end();it++)out[*it]--,change(1,*it,-1);
st[u].clear();
}else if(op==3){
scanf("%d%d",&u,&v);
out[u]++;
change(1,u,1);
st[v].insert(u);
}else{
scanf("%d",&u);
for(int i=head[u];i;i=nxt[i])st[u].insert(to[i]),out[to[i]]++,change(1,to[i],1);
}
if(qmax(1,1,n)==1&&qmin(1,1,n)==1)puts("YES");
else puts("NO");
}
return 0;
}