# bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集

## 题目大意:

n,q <= 50000. m <= 100000

## 题解:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define rg register int
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
const int maxm = 100010;
struct Edge{
int id;
int u,v,a,b;
}e[maxm],q[maxm],tmp[maxm];
int cnt;
inline bool cmpa(const Edge &a,const Edge &b){
return a.a == b.a ? a.b < b.b : a.a < b.a;
}
inline bool cmpb(const Edge &a,const Edge &b){
return a.b == b.b ? a.a < b.a : a.b < b.b;
}
int n,m;
struct Node{
int idx,idy,fa,siz,mxa,mxb;
Node(){}
Node(const int &a,const int &b,const int &c
,const int &d,const int &e,const int &f){
idx = a;idy = b;fa = c;siz = d;mxa = e;mxb = f;
}
}sta[maxm];
int top;
int fa[maxn],siz[maxn],mxa[maxn],mxb[maxn];
inline void clear(){
for(int i=1;i<=n;++i){
fa[i] = i;siz[i] = 1;
mxa[i] = mxb[i] = -1;
}
}
inline int find(int x){
while(x != fa[x]) x = fa[x];
return x;
}
inline void Union(const Edge &e){
int x = find(e.u),y = find(e.v);
if(siz[x] > siz[y]) swap(x,y);
sta[++top] = Node(x,y,fa[x],siz[y],mxa[y],mxb[y]);
mxa[y] = max(mxa[y],max(mxa[x],e.a));
mxb[y] = max(mxb[y],max(mxb[x],e.b));
if(x == y) return ;
siz[y] += siz[x];fa[x] = y;
}
inline void Undo(){
while(top){
fa[sta[top].idx] = sta[top].fa;
siz[sta[top].idy] = sta[top].siz;
mxa[sta[top].idy] = sta[top].mxa;
mxb[sta[top].idy] = sta[top].mxb;
-- top;
}
}
bool ans[maxm];
int main(){
for(int i=1;i<=m;++i){
}
for(int i=1;i<=Q;++i){
q[i].id = i;
}
sort(e+1,e+m+1,cmpa);sort(q+1,q+Q+1,cmpb);
int block = sqrt(m);
for(int i=1;i<=m;i+=block){
cnt = 0;
for(int j=1;j<=Q;++j){
if(q[j].a >= e[i].a && (i+block > m || e[i+block].a > q[j].a)){
tmp[++cnt] = q[j];
}
}
sort(e+1,e+i,cmpb);clear();
for(int j=1,k=1;j<=cnt;++j){
while(k < i && e[k].b <= tmp[j].b) Union(e[k++]);
top = 0;
for(int l=i;l<i+block && l <= m;++l){
if(e[l].a <= tmp[j].a && e[l].b <= tmp[j].b) Union(e[l]);
}
int x = find(tmp[j].u),y = find(tmp[j].v);
if(x == y && mxa[x] == tmp[j].a && mxb[x] == tmp[j].b) ans[tmp[j].id] = true;
Undo();
}
}
for(int i=1;i<=Q;++i) puts(ans[i] ? "Yes" : "No");
return 0;
}
`

posted @ 2017-04-05 05:56  Sky_miner  阅读(189)  评论(0编辑  收藏  举报