1. 程式人生 > >Codechef MARCH14 GERALD07加強版

Codechef MARCH14 GERALD07加強版

reg 封裝 space freopen spl stdout 個數 替換 const

強制在線不代表不能預處理!

考慮暴力怎麽幹?

開始n個聯通塊。now=n

不斷加入邊,如果連接兩個聯通塊,--now

否則不動。

後者的前提是和[l,id-1]的邊構成環

所以,我們考慮每個[l,r]中出現的邊能否第一次連接兩個聯通塊

預處理:

編號從小到大加入每條邊,LCT維護樹上“邊”編號最小值和最小值位置

如果加入邊e沒有環,那麽說明無論什麽時候[l,r]詢問包含e的時候,e總能是第一個連接兩個聯通塊的邊,設ti[e]=0,表示不能替換邊

如果會成環,那麽把編號最小的邊刪掉,ti[i]=被刪邊的編號。意義是,只有[l,r]不包含這條被刪除的邊的時候,e才會貢獻。

    如果包含,那麽這個環一定會連出來;如果不包含,e和這個環上其他的邊不會構成環,加入e的時候有貢獻。(如果會構成環,那麽環上邊和被刪邊之前也能構成環,矛盾)

所以,ti[i]在不在[l,r]之中,唯一對應了i能否真正連接兩個聯通塊!

所以對於詢問,主席樹維護即可。[l,r]中,ti[i]<l的數的個數sum,n-sum就是ans

實現細節:
LCT的編號別和原邊的編號混了。。。。

mi是最小邊編號(最小值),id是最小值的lct點的編號!

調半天~~~

吸取重組病毒的教訓,把主席樹封裝進namespace~~

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^‘0‘)
using namespace std;
typedef 
long long ll; il void rd(int &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch==-)&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=200000+5; const int inf=0x3f3f3f3f; struct bian{ int x,y; }e[N];
int n,m,k,typ; int ti[N]; namespace seg{ #define mid ((l+r)>>1) struct node{ int ls,rs; int val; }t[N*22]; int cnt; int rt[N]; void upda(int &x,int y,int l,int r,int to){ x=++cnt; t[x].val=t[y].val+1; if(l==r) return; t[x].ls=t[y].ls,t[x].rs=t[y].rs; if(to<=mid) upda(t[x].ls,t[y].ls,l,mid,to); if(mid<to) upda(t[x].rs,t[y].rs,mid+1,r,to); } int query(int x,int y,int l,int r,int L,int R){ //cout<<" l r "<<l<<" "<<r<<" : "<<t[x].val<<" "<<t[y].val<<" "<<L<<" "<<R<<endl; if(L<=l&&r<=R){ //cout<<" l r "<<l<<" "<<r<<" : "<<t[x].val<<" "<<t[y].val<<" "<<L<<" "<<R<<endl; return t[x].val-t[y].val; } int ret=0; if(L<=mid) ret+=query(t[x].ls,t[y].ls,l,mid,L,R); if(mid<R) ret+=query(t[x].rs,t[y].rs,mid+1,r,L,R); return ret; } void add(int x,int to){ upda(rt[x],rt[x-1],0,m,to); } } namespace lct{ #define ls t[x].ch[0] #define rs t[x].ch[1] struct node{ int ch[2]; int fa,r; int id; int mi; int d; }t[2*N]; int sta[N]; int cnt; bool nrt(int x){ return (t[t[x].fa].ch[0]==x||t[t[x].fa].ch[1]==x); } void pushup(int x){ if(t[t[x].ch[0]].mi<=t[x].d&&t[t[x].ch[0]].mi<=t[t[x].ch[1]].mi){ t[x].mi=t[t[x].ch[0]].mi; t[x].id=t[t[x].ch[0]].id; } else if(t[t[x].ch[1]].mi<=t[x].d&&t[t[x].ch[1]].mi<=t[t[x].ch[0]].mi){ t[x].mi=t[t[x].ch[1]].mi; t[x].id=t[t[x].ch[1]].id; } else t[x].mi=t[x].d,t[x].id=x; } void rev(int x){ swap(t[x].ch[0],t[x].ch[1]); t[x].r^=1; } void pushdown(int x){ if(t[x].r){ rev(t[x].ch[1]),rev(t[x].ch[0]); t[x].r=0; } } void rotate(int x){ int y=t[x].fa,d=t[y].ch[1]==x; t[t[y].ch[d]=t[x].ch[!d]].fa=y; if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x; else t[x].fa=t[y].fa; t[t[x].ch[!d]=y].fa=x; pushup(y); } void splay(int x){ int y=x,z=0; sta[++z]=y; while(nrt(y)) y=t[y].fa,sta[++z]=y; while(z) pushdown(sta[z--]); while(nrt(x)){ y=t[x].fa,z=t[y].fa; // cout<<"splaying "<<x<<" "<<y<<" "<<z<<endl; if(nrt(y)){ rotate(((t[z].ch[1]==y)==(t[y].ch[1]==x))?y:x); } rotate(x); } pushup(x); } void access(int x){ for(reg y=0;x;y=x,x=t[x].fa){ splay(x);t[x].ch[1]=y;pushup(x); // cout<<" access xx "<<x<<" "<<t[x].fa<<endl; } } void makert(int x){ access(x);splay(x);rev(x); } int findrt(int x){ access(x);splay(x); // cout<<" after splay "<<x<<endl; pushdown(x); while(t[x].ch[0]) { x=t[x].ch[0],pushdown(x); // cout<<"findrt xx "<<x<<endl; } splay(x); return x; } int link(int x,int y,int d){ // cout<<" link "<<x<<" "<<y<<" : "<<d<<" cnt "<<cnt<<endl; makert(x); // cout<<" makert "<<endl; ++cnt; t[cnt].d=d; t[cnt].id=cnt; t[cnt].mi=d; if(findrt(y)!=x){ // cout<<" new "<<endl; access(y);splay(y); t[x].fa=cnt; t[cnt].fa=y; return 0; } pushup(x); splay(x); int kil=t[x].id; int lp=t[x].mi; // cout<<" ---------------------kil "<<kil<<endl; splay(kil); // cout<<" kilfa "<<t[kil].fa<<endl; t[t[kil].ch[0]].fa=0; t[t[kil].ch[1]].fa=0; makert(x); splay(x);splay(y); t[x].fa=cnt; t[cnt].fa=y; //cout<<" t[x].id "<<t[x].id<<" t[y].id "<<t[y].id<<endl; return lp; } } int main(){ lct::t[0].id=-1; lct::t[0].d=inf; lct::t[0].mi=inf; rd(n);rd(m);rd(k);rd(typ); for(reg i=1;i<=n;++i) lct::t[i].d=inf,lct::t[i].id=-1,lct::t[i].mi=inf; lct::cnt=n; int x,y; for(reg i=1;i<=m;++i){ rd(x);rd(y); if(x!=y) ti[i]=lct::link(x,y,i); else ti[i]=i; //cout<<" ii "<<i<<" "<<ti[i]<<endl; } for(reg i=1;i<=m;++i){ seg::add(i,ti[i]); } int l,r; int las=0; while(k--){ rd(l);rd(r); if(typ==1) l^=las,r^=las; int tmp=seg::query(seg::rt[r],seg::rt[l-1],0,m,0,l-1); printf("%d\n",n-tmp); las=n-tmp; } return 0; } } signed main(){ //freopen("data.in","r",stdin); // freopen("my.out","w",stdout); Miracle::main(); return 0; } /* Author: *Miracle* Date: 2018/12/30 21:24:18 */

Codechef MARCH14 GERALD07加強版