[bzoj3514][CodeChef GERALD07] Chef ans Graph Queries [LCT+主席樹]

來源:互聯網
上載者:User

標籤:php   down   最小   基礎   rev   algorithm   out   pair   答案   

題面

bzoj上的強制線上版本

思路

首先可以確定,這類聯通塊相關的詢問問題,都可以$LCT$+可持久化記錄解決

用LCT維護產生樹作為演算法基礎

具體而言,從前往後按照邊的編號順序掃一遍邊

如果這條邊兩端不在同一個$LCT$聯通塊中,則$link$

否則$cut$掉當前串連兩條邊的路徑上的編號最小的邊,並$link$

記錄$ntr[i]$表示第$i$條邊觸發第二種情況時$link$前$cut$掉的邊的編號

如果觸發第一種情況,則$ntr[i]=0$

如果為自環,則$ntr[i]=i$

這樣記錄之後,建立$ntr[i]$的主席樹,每次在$ntr[i]$的位置+1

對於查詢$[l,r]$,$Ans=n-query(0,l-1,root[l-1],root[r])$

具體原因為:考慮每個$ntr$值大於等於$l$的邊,顯然它們在不在對答案都沒有貢獻(因為已經被ntr了)

否則,它們會串連兩個聯通塊,但是這條邊不在$[l,r]$區間內,所以有聯通塊個數-1的貢獻

Code
#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#define mp make_pairusing namespace std;inline int read(){    int re=0,flag=1;char ch=getchar();        while(!isdigit(ch)){        if(ch=='-') flag=-1;            ch=getchar();        }        while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();    return re*flag;}int fa[400010],ch[400010][2],val[400010],minn[400010],rev[400010];void update(int x){    minn[x]=x;    if(val[minn[x]]>val[minn[ch[x][0]]]) minn[x]=minn[ch[x][0]];    if(val[minn[x]]>val[minn[ch[x][1]]]) minn[x]=minn[ch[x][1]];}int nroot(int x){return ((ch[fa[x]][0]==x)||(ch[fa[x]][1]==x));}int get(int x){return ch[fa[x]][1]==x;}void pushrev(int x){    if(!x) return;    swap(ch[x][0],ch[x][1]);    rev[x]^=1;}void pushdown(int x){    if(!rev[x]) return;    pushrev(ch[x][0]);    pushrev(ch[x][1]);    rev[x]=0;}void push(int x){    if(!x) return;    if(nroot(x)) push(fa[x]);    pushdown(x);}void rotate(int x){    int f=fa[x],ff=fa[f],son=get(x),nr=nroot(f);//  cout<<"     rotate "<<x<<' '<<f<<' '<<ff<<' '<<son<<' '<<ch[x][0]<<' '<<ch[x][1]<<' '<<ch[f][0]<<' '<<ch[f][1]<<'\n';    ch[f][son]=ch[x][son^1];    if(ch[f][son]) fa[ch[f][son]]=f;    fa[f]=x;ch[x][son^1]=f;    fa[x]=ff;    if(nr) ch[ff][ch[ff][1]==f]=x;    update(f);update(x);}void splay(int x){//  cout<<" splay "<<x<<'\n';    push(x);    for(int f;nroot(x);rotate(x)){        f=fa[x];        if(nroot(f))            rotate((get(x)==get(f))?f:x);    }}void access(int x){//  cout<<"access "<<x<<'\n';    for(int y=0;x;y=x,x=fa[x]){        splay(x);ch[x][1]=y;update(x);//      cout<<" do "<<x<<' '<<fa[x]<<' '<<y<<'\n';    }}void mroot(int x){    access(x);splay(x);pushrev(x);}void link(int u,int v){    mroot(u);fa[u]=v;}void cut(int u,int v){    mroot(u);access(v);splay(v);    fa[u]=ch[v][0]=0;}int find(int u){    access(u);splay(u);    while(ch[u][0]) u=ch[u][0];    return u;}int query(int u,int v){    mroot(u);access(v);splay(v);    return minn[v];}int lc[4000010],rc[4000010],seg[4000010],cnt;int ntr[400010],root[400010];int insert(int l,int r,int pre,int pos){    int cur=++cnt,mid=(l+r)>>1;    lc[cur]=lc[pre];rc[cur]=rc[pre];seg[cur]=seg[pre]+1;    if(l==r) return cur;    if(mid>=pos) lc[cur]=insert(l,mid,lc[pre],pos);    else rc[cur]=insert(mid+1,r,rc[pre],pos);    return cur;}int query(int l,int r,int ql,int qr,int pre,int cur){    if(l>=ql&&r<=qr) return seg[cur]-seg[pre];    int mid=(l+r)>>1,re=0;    if(mid>=ql) re+=query(l,mid,ql,qr,lc[pre],lc[cur]);    if(mid<qr) re+=query(mid+1,r,ql,qr,rc[pre],rc[cur]);    return re;}int n,m,q;void init(){    n=read();m=read();q=read();cnt=0;    memset(lc,0,sizeof(lc));memset(rc,0,sizeof(rc));memset(seg,0,sizeof(seg));    for(int i=1;i<=n;i++) fa[i]=ch[i][0]=ch[i][1]=0,minn[i]=i,val[i]=1e9,rev[i]=0;    val[0]=1e9;}pair<int,int>e[200010];int main(){    int T=read(),i,t1,t2,tmp,w;    while(T--){        init();//      cout<<n<<' '<<m<<' '<<q<<'\n';        for(i=1;i<=m;i++){            t1=read();t2=read();            e[i]=mp(t1,t2);//          cout<<"input "<<t1<<' '<<t2<<'\n';            if(t1==t2){ntr[i]=i;continue;}            if(find(t1)==find(t2)){                tmp=query(t1,t2);w=val[tmp];                ntr[i]=w;                cut(tmp,e[w].first);                cut(tmp,e[w].second);            }            else ntr[i]=0;//          cout<<"passed "<<ntr[i]<<'\n';            fa[n+i]=ch[n+i][0]=ch[n+i][1]=0;            val[n+i]=i;minn[n+i]=n+i;rev[n+i]=0;            link(n+i,t1);link(n+i,t2);        }        for(i=1;i<=m;i++) root[i]=insert(0,m,root[i-1],ntr[i]);        for(i=1;i<=q;i++){            t1=read();t2=read();            printf("%d\n",n-query(0,m,0,t1-1,root[t1-1],root[t2]));        }    }}

[bzoj3514][CodeChef GERALD07] Chef ans Graph Queries [LCT+主席樹]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.