标签:i++ getc written loser 在线 pair swap 动态 lse
线段树分治板子。这种动态图的问题看都不要看,大概率可以用线段树分治。
我们有一堆的集合,每次把这个集合的边删掉,问你每个时刻的连通性。
我们只需要把这个时刻删去的集合里的边删掉,也就是这个区间不用加这条边,按常规把边扔到线段树上,遍历一下,每个点的连通性就出来了。
拿样例举个例子:
4 5
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2
遍历即可。
//Don‘t act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you‘ll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
#define int long long
#define pr pair<int,int>
using namespace std;
int read() {
char ch=getchar();
int f=1,x=0;
while(ch<‘0‘||ch>‘9‘) {
if(ch==‘-‘)
f=-1;
ch=getchar();
}
while(ch>=‘0‘&&ch<=‘9‘) {
x=x*10+ch-‘0‘;
ch=getchar();
}
return f*x;
}
const int MAXN=4e5+10,MAXQ=2e5+10;
int n,m,q,cnt,num;
stack<pr > stk;
int size[MAXN],father[MAXN],a[MAXN],ans[MAXQ];
vector<int > edge[MAXQ<<2];
pr e[MAXN];
pr make_edge(int x,int y) {
return make_pair(min(x,y),max(x,y));
}
int find(int x) {
if(x!=father[x]) {
return find(father[x]);
}
return x;
}
void merge(pr s) {
int x=find(s.first);
int y=find(s.second);
if(x==y) {
stk.push(make_pair(-1,-1));
return ;
}
num--;
if(size[x]>size[y]) {
swap(x,y);
}
father[x]=y;
size[y]+=size[x];
stk.push(make_pair(x,y));
}
void del() {
int x=stk.top().first;
int y=stk.top().second;
stk.pop();
if(x==-1) {
return ;
}
num++;
father[x]=x;
size[y]-=size[x];
}
void modify(int l,int r,int p,int x,int y,int s) {
if(x>y||r<x||y<l) {
return ;
}
if(x<=l&&r<=y) {
edge[p].push_back(s);
return ;
}
int mid=(l+r)>>1;
modify(l,mid,p<<1,x,y,s);
modify(mid+1,r,p<<1|1,x,y,s);
}
void query(int l,int r,int p) {
int sz=edge[p].size();
for(int i=0;i<sz;i++) {
merge(e[edge[p][i]]);
}
if(l==r) {
if(num==1) {
ans[l]=1;
}
else {
ans[l]=0;
}
}
else {
int mid=(l+r)>>1;
query(l,mid,p<<1);
query(mid+1,r,p<<1|1);
}
while(sz--) {
del();
}
}
signed main() {
cin>>n>>m;
num=n;
for(int i=1;i<=n;i++) {
father[i]=i;
size[i]=i;
}
for(int i=1;i<=m;i++) {
e[i]=make_edge(read(),read());
a[i]=1;
}
cin>>q;
for(int i=1;i<=q;i++) {
int k=read();
while(k--) {
int c=read();
modify(1,q,1,a[c],i-1,c);
a[c]=i+1;
}
}
for(int i=1;i<=m;i++) {
modify(1,q,1,a[i],q,i);
}
query(1,q,1);
for(int i=1;i<=q;i++) {
if(ans[i]) {
printf("Connected\n");
}
else {
printf("Disconnected\n");
}
}
return 0;
}
标签:i++ getc written loser 在线 pair swap 动态 lse
原文地址:https://www.cnblogs.com/huayucaiji/p/LG5227.html