传送门
文章目录
- 题意:
- 思路:
题意:
思路:
线段树分治就是在线段树上进行遍历,到每个点都加上它对子节点的贡献,最后到叶子节点的时候算一下贡献。
对于这个题先考虑维护二分图的话,可以用扩展域并查集维护。
而对于每条边,他有出现时间和消失时间,我们按照时间来建一颗线段树,让后可以将他出现的时间[l,r][l,r][l,r]在线段树上切分成lognlognlogn段,对于每段都分别管理着不同的叶子节点。我们可以用vectorvectorvector存下来管理当前这颗子树的边,让后把他们连上,判断一下是否是二分图,不是的话当前[l,r][l,r][l,r]时间段都不是二分图,否则就继续遍历,最后回溯的时候用可撤销并查集撤销一下就好了。
注意并查集不能路径压缩,因为我们还要撤销。
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,m,k;
int p[N],se[N];
PII edge[N];
stack<PII>s;
struct Node
{int l,r;vector<int>v;
}tr[N<<2];void build(int u,int l,int r)
{tr[u]={l,r};if(l==r) return;build(L,l,Mid); build(R,Mid+1,r);
}void insert(int u,int l,int r,int id)
{if(tr[u].l>=l&&tr[u].r<=r){tr[u].v.push_back(id);return;}if(l<=Mid) insert(L,l,r,id);if(r>Mid) insert(R,l,r,id);
}int find(int x) { return x==p[x]? x:find(p[x]); }void merge(int a,int b)
{if(a==b) return;if(se[a]<se[b]) swap(a,b);p[b]=a; se[a]+=se[b];s.push({b,se[b]});
}void dfs(int u,int l,int r)
{int flag=1,beg=s.size();for(int i=0;i<tr[u].v.size();i++){int id=tr[u].v[i];int pa=find(edge[id].X),pb=find(edge[id].Y);if(pa==pb) { flag=0; break; }merge(pa,find(edge[id].Y+n)),merge(find(edge[id].X+n),pb);}if(flag){if(l==r) puts("Yes");else dfs(L,l,Mid),dfs(R,Mid+1,r);}else for(int i=l;i<=r;i++) puts("No");while(s.size()>beg) se[find(s.top().X)]-=s.top().Y,p[s.top().X]=s.top().X,s.pop();
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n*2;i++) p[i]=i,se[i]=1;build(1,1,k);for(int i=1;i<=m;i++){int x,y,l,r; scanf("%d%d%d%d",&x,&y,&l,&r);if(l!=r) insert(1,l+1,r,i);edge[i]={x,y};}dfs(1,1,k);return 0;
}
/**/