【刷題】BZOJ 4025 二分圖
阿新 • • 發佈:2018-04-09
-o 情況 問題 split i+1 else find spl for
然後看動態的,動態的麻煩就在刪除,因為可能把一條樹邊刪掉之後,會有一條非樹邊代替它變成一條樹邊,這個做不了;所以就弄一個LCT維護這個樹,維護這個圖以刪除時間為關鍵字的最大生成樹,這樣就不會有上述情況發生了
然後按照套路,離線解決
(PS:從早上開始調,一直調到晚上,開始的時候造數據的程序還寫錯了,會使標程RE,然後有一次其實改對了,但因為數據造錯,一直拍不上,結果就和gt拿了一個正確的程序調了半個小時)
Description
神犇有一個n個節點的圖。因為神犇是神犇,所以在T時間內一些邊會出現後消失。神犇要求出每一時間段內這個圖是否是二分圖。這麽簡單的問題神犇當然會做了,於是他想考考你。
Input
輸入數據的第一行是三個整數n,m,T。
第2行到第m+1行,每行4個整數u,v,start,end。第i+1行的四個整數表示第i條邊連接u,v兩個點,這條邊在start時刻出現,在第end時刻消失。
Output
輸出包含T行。在第i行中,如果第i時間段內這個圖是二分圖,那麽輸出“Yes”,否則輸出“No”,不含引號。
Sample Input
3 3 3
1 2 0 2
2 3 0 3
1 3 1 2
Sample Output
Yes
No
Yes
HINT
樣例說明:
0時刻,出現兩條邊1-2和2-3。
第1時間段內,這個圖是二分圖,輸出Yes。
1時刻,出現一條邊1-3。
第2時間段內,這個圖不是二分圖,輸出No。
2時刻,1-2和1-3兩條邊消失。
第3時間段內,只有一條邊2-3,這個圖是二分圖,輸出Yes。
數據範圍:
n<=100000,m<=200000,T<=100000,1<=u,v<=n,0<=start<=end<=T。
Solution
這題害了我一天
首先看怎麽靜態判能不能二分,一條一條邊加進去,如果這條邊加上會變成一個環,並且這個環還是奇環,那就不能二分;反之,可以
然後按照套路,離線解決
(PS:從早上開始調,一直調到晚上,開始的時候造數據的程序還寫錯了,會使標程RE,然後有一次其實改對了,但因為數據造錯,一直拍不上,結果就和gt拿了一個正確的程序調了半個小時)
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10,MAXM=200000+10,inf=0x3f3f3f3f;
int n,m,tT,V[MAXN+MAXM],sum,f[MAXN+MAXM];
struct edge{
int u,v;
};
edge side[MAXM];
struct data{
int opt,val,t,id;
inline bool operator < (const data &A) const {
return t<A.t||t==A.t&&opt>A.opt;
};
};
data p[MAXM<<1];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
int ch[MAXN+MAXM][2],fa[MAXN+MAXM],rev[MAXN+MAXM],Mn[MAXN+MAXM],id[MAXN+MAXM],stack[MAXN+MAXM],cnt,val[MAXN+MAXM],size[MAXN+MAXM];
inline void init()
{
memset(Mn,inf,sizeof(Mn));
memset(val,inf,sizeof(val));
}
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void pushup(int x)
{
size[x]=size[lc(x)]+size[rc(x)]+1;
Mn[x]=val[x],id[x]=x;
if(Mn[lc(x)]<Mn[x])Mn[x]=Mn[lc(x)],id[x]=id[lc(x)];
if(Mn[rc(x)]<Mn[x])Mn[x]=Mn[rc(x)],id[x]=id[rc(x)];
}
inline void pushdown(int x)
{
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
}
inline int findroot(int x)
{
access(x);splay(x);
while(lc(x))pushdown(x),x=lc(x);
splay(x);
return x;
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y)
{
makeroot(x);fa[x]=y;
}
inline void cut(int x,int y)
{
split(x,y);fa[x]=lc(y)=0;pushup(y);
}
};
LCT T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void add(int now)
{
int u=side[p[now].id].u,v=side[p[now].id].v,sn=p[now].id+n;
if(u==v)
{
f[sn-n]=1;sum++;
return ;
}
if(T.findroot(u)!=T.findroot(v))T.val[sn]=p[now].val,T.link(sn,u),T.link(sn,v),V[sn-n]=1;
else
{
T.split(u,v);
int so=T.id[v],nt=T.size[v]>>1;
if(p[now].val>T.Mn[v])
{
if(!(nt&1))sum++,f[so-n]=1;
T.cut(so,side[so-n].u);
T.cut(so,side[so-n].v);
T.val[sn]=p[now].val;
T.link(sn,u);
T.link(sn,v);
V[so-n]=0;V[sn-n]=1;
}
else if(!(nt&1))sum++,f[sn-n]=1;
}
}
inline void del(int now)
{
int sn=p[now].id+n;
sum-=f[sn-n];
if(V[sn-n])
{
V[sn-n]=f[sn-n]=0;
T.cut(sn,side[sn-n].u);T.cut(sn,side[sn-n].v);
}
else f[sn-n]=0;
}
int main()
{
read(n);read(m);read(tT);
for(register int i=1;i<=m;++i)
{
int u,v,st,ed;
read(u);read(v);read(st);read(ed);
side[i].u=u;side[i].v=v;
p[i].t=st;p[i].val=ed;p[i].id=i;p[i].opt=1;
p[i+m].t=ed;p[i+m].id=i;p[i+m].opt=0;
}
std::sort(p+1,p+m*2+1);
T.init();
for(register int i=1,j=1;i<=tT;++i)
{
for(;p[j].t<i&&j<=m*2;++j)
if(p[j].opt)add(j);
else del(j);
if(sum)puts("No");
else puts("Yes");
}
return 0;
}
【刷題】BZOJ 4025 二分圖