时间线段树+启发式合并并查集
启发式合并并查集只需要记录下合并前的转态,合并的时候按秩合并,然后根据之前记录的状态回退就好了
我的代码常数有点大(早上交T了,晚上就卡着过了)
/**************************************************************
Problem: 4025
User: syh0313
Language: C++
Result: Accepted
Time:19968 ms
Memory:35456 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cassert>
#define lch a[n].lc
#define rch a[n].rc
#define pb push_back
using
namespace
std;
const
int
maxn=200010;
int
n,m,t,u[maxn],v[maxn],root,topt,fa[maxn],si[maxn],dep[maxn],ct;
struct
da{
int
lc,rc;}a[4*maxn];
vector<
int
>now[4*maxn];
bool
f[maxn];
int
read()
{
int
xx=0,ff=1;
char
c=
getchar
();
while
(c<
'0'
|| c>
'9'
) {
if
(c==
'-'
) ff=-1; c=
getchar
();}
while
(c>=
'0'
&& c<=
'9'
) {xx=(xx<<1)+(xx<<3)+c-
'0'
; c=
getchar
();}
return
xx*ff;
}
da getf(
int
x)
{
if
(++ct>=20000000)
assert
(0);
if
(x==fa[x])
return
{x,0};
da now=getf(fa[x]); now.rc+=dep[x];
return
now;
}
void
build_tree(
int
&n,
int
l,
int
r)
{
n=++topt;
if
(l==r)
return
;
int
mid=(l+r)>>1;
build_tree(lch,l,mid); build_tree(rch,mid+1,r);
}
void
tree_add(
int
n,
int
L,
int
R,
int
l,
int
r,
int
k)
{
if
(L==l && R==r) {now[n].pb(k);
return
;}
int
mid=(L+R)>>1;
if
(r<=mid) tree_add(lch,L,mid,l,r,k);
else
if
(l>=mid+1) tree_add(rch,mid+1,R,l,r,k);
else
tree_add(lch,L,mid,l,mid,k),tree_add(rch,mid+1,R,mid+1,r,k);
}
void
qury(
int
n,
int
l,
int
r,
int
ok)
{
vector<
int
>rep,res,red;
bool
ff=1;
if
(now[n].size())
{
for
(
int
i=0;i<(
int
)now[n].size();i++)
{
int
fr=u[now[n][i]],to=v[now[n][i]];
da now1=getf(fr),now2=getf(to);
if
(now1.lc==now2.lc)
{
if
(!(
abs
(now1.rc-now2.rc)&1)) ff=0;
continue
;
}
if
(si[now1.lc]<si[now2.lc]) swap(now1,now2);
rep.pb(now1.lc); res.pb(si[now1.lc]); red.pb(dep[now1.lc]);
rep.pb(now2.lc); res.pb(si[now2.lc]); red.pb(dep[now2.lc]);
fa[now2.lc]=now1.lc; dep[now2.lc]=now1.rc+now2.rc+1; si[now1.lc]+=si[now2.lc];
}
}
if
(l==r) f[l]=ok&&ff;
else
if
(ok&&ff) {
int
mid=(l+r)>>1; qury(lch,l,mid,ok&&ff); qury(rch,mid+1,r,ok&&ff);}
for
(
int
i=rep.size()-1;i>=0;i--) {fa[rep[i]]=rep[i]; si[rep[i]]=res[i]; dep[rep[i]]=red[i];}
}
int
main()
{
n=read(); m=read(); t=read(); build_tree(root,1,t);
for
(
int
i=1;i<=n;i++) fa[i]=i,si[i]=1;
for
(
int
i=1;i<=m;i++)
{
u[i]=read(); v[i]=read();
int
l,r; l=read()+1; r=read();
if
(l>r)
continue
;
tree_add(root,1,t,l,r,i);
}
qury(root,1,t,1);
for
(
int
i=1;i<=t;i++)
printf
(f[i]?
"Yes\n"
:
"No\n"
);
return
0;
}