zoukankan      html  css  js  c++  java
  • BZOJ3514 Codechef MARCH14 GERALD07加强版

    Link
    这道题需要一个比较巧妙的转化。
    首先我们知道连通块个数等于点数减树边数。
    假如现在是第(i)时刻,我们加入一条边形成了一个环,环上最早加入的边是(ntr_i=j)时刻的。相当于第(i)条边把第(ntr_i)条边挤出去了。(如果加入第(i)条边不会生成环,那么(ntr_i=0)。如果第(i)条边是个自环,那么(ntr_i=i)。)
    那么对于询问(l,r),如果有(ntr_i<lle ile r),那么这第(i)条边边会对这个询问产生一个边数的贡献。
    那么我们二维数点即可。因为是强制在线所以需要主席树。
    至于这个(ntr),我们可以使用LCT维护动态生成树来求。
    至于这个数组名称是什么意思,我怎么知道?

    #include<bits/stdc++.h>
    using namespace std;
    namespace IO
    {
        char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[11],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
        char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
        void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
        void Put(char x){*oS++=x;if(oS==oT)Flush();}
        int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
        void write(int x){int top=0;while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('
    ');}
    }
    using IO::read;using IO::write;using IO::Flush;
    int min(int a,int b){return a<b? a:b;}
    const int N=200007;
    int n,m,Q,o,ntr[N];
    struct edge{int u,v;}e[N];
    namespace LCT
    {
        int ch[N<<1][2],fa[N<<1],rev[N<<1],mn[N<<1];
    #define lc ch[x][0]
    #define rc ch[x][1]
        int nroot(int x){return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
        void pushup(int x)
        {
    	mn[x]=x;
    	if(lc) mn[x]=min(mn[x],mn[lc]);
    	if(rc) mn[x]=min(mn[x],mn[rc]);
        }
        void pushrev(int x){swap(lc,rc),rev[x]^=1;}
        void pushdown(int x){if(!rev[x])return;rev[x]=0;if(lc)pushrev(lc);if(rc)pushrev(rc);}
        void pushall(int x){if(nroot(x))pushall(fa[x]);pushdown(x);}
        void rotate(int x)
        {
    	int y=fa[x],z=fa[y],k=ch[y][1]==x;
    	if(nroot(y)) ch[z][ch[z][1]==y]=x;
    	fa[x]=z,fa[ch[x][!k]]=y,ch[y][k]=ch[x][!k],fa[y]=x,ch[x][!k]=y,pushup(y),pushup(x);
        }
        void splay(int x)
        {
    	pushall(x);
    	for(int y;nroot(x);rotate(x)) if(nroot(y=fa[x])) rotate((ch[fa[y]][0]==y)^(ch[y][0]==x)? x:y);
        }
        void access(int x){for(int y=0;x;x=fa[y=x])splay(x),rc=y,pushup(x);}
        void makeroot(int x){access(x),splay(x),pushrev(x);}
        int findroot(int x){access(x),splay(x);while(lc)x=lc;return splay(x),x;}
        void split(int x,int y){makeroot(x),access(y),splay(y);}
        void link(int x,int y){makeroot(x),fa[x]=y;}
        void cut(int x,int y){split(x,y),ch[y][0]=fa[x]=0,pushup(y);}
        int ask(int x,int y){return split(x,y),mn[y];}
    #undef lc
    #undef rc
    }using namespace LCT;
    void Kruskal()
    {
        for(int i=1,u,v,x;i<=m;++i)
        {
    	if((u=e[i].u)==(v=e[i].v)) {ntr[i]=i;continue;}
    	if(findroot(u)==findroot(v)) x=ask(u,v),ntr[i]=x,cut(e[x].u,x),cut(e[x].v,x);
    	link(u,i),link(v,i);
        }
    }
    namespace JiangTree
    {
    #define mid ((l+r)>>1)
        int L[N<<5],R[N<<5],sum[N<<5],root[N],cnt=0;
        void insert(int &p,int l,int r,int x)
        {
    	L[++cnt]=L[p],R[cnt]=R[p],sum[cnt]=sum[p]+1,p=cnt;
    	if(l==r) return ;
    	x<=mid? insert(L[p],l,mid,x):insert(R[p],mid+1,r,x);
        }
        int query(int u,int v,int l,int r,int ql,int qr)
        {
    	if(ql<=l&&r<=qr) return sum[v]-sum[u];
    	return (ql<=mid? query(L[u],L[v],l,mid,ql,qr):0)+(qr>mid? query(R[u],R[v],mid+1,r,ql,qr):0);
        }
    #undef mid
    }using namespace JiangTree;
    void solve()
    {
        int ans=0;
        for(int i=1;i<=m;++i) insert(root[i]=root[i-1],0,m,ntr[i]);
        for(int l,r;Q;--Q) l=read()^(ans*o),r=read()^(ans*o),write(ans=n-query(root[l-1],root[r],0,m,0,l-1));
    }
    int main()
    {
        n=read(),m=read(),Q=read(),o=read();
        for(int i=1;i<=m;++i) e[i].u=read()+m,e[i].v=read()+m;
        Kruskal(),solve();
        return Flush(),0;
    }
    
  • 相关阅读:
    设计模式走一遍---观察者模式
    从0打卡leetcode之day 6--最长回文串
    回车与换行的故事
    线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)
    线程安全(上)--彻底搞懂volatile关键字
    从0打卡leetcode之day 5 ---两个排序数组的中位数
    聊一聊让我蒙蔽一晚上的各种常量池
    从零打卡leetcode之day 4--无重复最长字符串
    C4.5算法总结
    数据库游标使用
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11991643.html
Copyright © 2011-2022 走看看