题目大意:给定一张
n
个点
这显然是一个动态二分图问题,分治并查集解法戳这里
但是这道题我们并不知道每条边的具体存在时间
因此我们这样:
假设每次修改都生效,我们把每条边的第一种颜色的存在时间加入分治结构(其实就是线段树)
DFS的过程中,如果DFS到一个叶节点时,判断当前修改能否执行,这样我们就得到了这条边在下一个时间段的颜色,然后将这条边的下一个时间段加入分治结构
时间复杂度
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 500500
#define col first
#define num second
#define time second
#define operation second
using namespace std;
int n,m,k,q;
struct edge{
int x,y;
}edges[M];
pair<int,int> queries[M];
//first-color second-edge number
queue<pair<int,int> > modifictions[M];
//first-color second-time
vector<pair<int,int> > v[M<<2];
//first-color second-edge number
struct Union_Find_Set;
pair<Union_Find_Set*,int> stack[M<<2];int top;
//first-color second-operation
int color[M];
struct Union_Find_Set{
int fa[M];
char rank[M],dis[M];
int Find(int x)
{
if(!fa[x])
return x;
return Find(fa[x]);
}
int Distance(int x)
{
if(!fa[x])
return 0;
return dis[x]^Distance(fa[x]);
}
void Union(int x,int y)
{
int fx=Find(x),fy=Find(y);
if(fx==fy) return ;
if(rank[fx]>rank[fy])
swap(x,y),swap(fx,fy);
if(rank[fx]==rank[fy])
++rank[fy],stack[++top]=pair<Union_Find_Set*,int>(this,-fy);
dis[fx]=Distance(x)^Distance(y)^1;
fa[fx]=fy;
stack[++top]=pair<Union_Find_Set*,int>(this,fx);
}
}dsu[51];
void Restore(int bottom)
{
while(top>bottom)
{
if(stack[top].second<0)
stack[top].first->rank[-stack[top].second]--;
else
stack[top].first->fa[stack[top].second]=0;
top--;
}
}
void Insert(int p,int x,int y,int l,int r,pair<int,int> val)
{
int mid=x+y>>1;
if(x==l&&y==r)
{
v[p].push_back(val);
return ;
}
if(r<=mid)
Insert(p<<1,x,mid,l,r,val);
else if(l>mid)
Insert(p<<1|1,mid+1,y,l,r,val);
else
Insert(p<<1,x,mid,l,mid,val) , Insert(p<<1|1,mid+1,y,mid+1,r,val);
}
void Divide_And_Conquer(int p,int x,int y)
{
int i,mid=x+y>>1,bottom=top;
for(i=0;i<(signed)v[p].size();i++)
{
int x=edges[v[p][i].second].x;
int y=edges[v[p][i].second].y;
dsu[v[p][i].first].Union(x,y);
}
if(x==y)
{
Union_Find_Set &dsu=::dsu[queries[mid].col];
int x=edges[queries[mid].num].x;
int y=edges[queries[mid].num].y;
if( dsu.Find(x)!=dsu.Find(y) || dsu.Distance(x)^dsu.Distance(y) )
puts("YES"),color[queries[mid].num]=queries[mid].col;
else
puts("NO");
modifictions[queries[mid].num].pop();
if(mid!=q)
Insert(1,1,q,mid+1,modifictions[queries[mid].num].front().time,pair<int,int>(color[queries[mid].num],queries[mid].num));
}
else
Divide_And_Conquer(p<<1,x,mid),Divide_And_Conquer(p<<1|1,mid+1,y);
Restore(bottom);
}
int main()
{
#ifdef PoPoQQQ
//freopen("576E.in","r",stdin);
//freopen("576E.out","w",stdout);
#endif
int i;
cin>>n>>m>>k>>q;
for(i=1;i<=m;i++)
scanf("%d%d",&edges[i].x,&edges[i].y);
for(i=1;i<=q;i++)
{
scanf("%d%d",&queries[i].num,&queries[i].col);
modifictions[queries[i].num].push(pair<int,int>(queries[i].col,i));
}
for(i=1;i<=m;i++)
modifictions[i].push(pair<int,int>(0,q));
Divide_And_Conquer(1,1,q);
return 0;
}