zoukankan      html  css  js  c++  java
  • P3224 [HNOI2012]永无乡

    事实证明,没过对拍的代码都不一定是对的。我写的那个代码,漏洞多多的,拍出来的第一组数据过不去的,AC绿绿的。

    这题思路其实挺简单的,一句话题意就是带合并的区间k大,这里的合并用线段树合并和splay启发式合并都可以,我写的是splay。有个结论,splay按照中序遍历合并,复杂度能少一个log。

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    #define forg(i,x) for(int i=first[x];i;i=nxt[i])
    #define uu unsigned
    #define fi first
    #define se second
    #define od(x) ((x)&1)
    #define ev(x) (od(x)^1)
    #define mi2(x) (1<<(x))
    #define scanf a1234=scanf
    #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
    int a1234;
    char buf[1<<18],*bufs=buf,*buft=buf;
    inline int gc(){
        return bufs==buft&&(buft=(bufs=buf)+fread(buf,1,1<<18,stdin)),bufs==buft?-1:*bufs++;
    }
    inline void xxx(){for(;;);}
    
    const int mxn=1e5+3;
    int n,m,q,w[mxn];
    class unio{
        public:
        int fa[mxn],siz[mxn];
        inline void init(){
            for(int i=1;i<=n;++i)fa[i]=i,siz[i]=1;
        }
        inline int find(int x){
            while(x!=fa[x])x=fa[x]=fa[fa[x]];
            return x;
        }
        inline void merge(int x,int y){
            x=find(x),y=find(y);fa[x]=y,siz[y]+=siz[x];
        }
    }us;
    #define lch ch[0]
    #define rch ch[1]
    struct node{
        node*ch[2],*prt;
        int val,siz,xh;
        inline void up(){siz=lch->siz+rch->siz+1;}
    }*nil,ap[mxn];
    class PSL{
        public:
        node*po[mxn],*rt[mxn];
        inline void init(){
            nil=&ap[0];
            nil->lch=nil->rch=nil->prt=nil;
            nil->siz=0;
            for(int i=1;i<=n;++i)po[i]=newd(i,nil);
            memcpy(rt,po,sizeof(po));
        }
        inline node*newd(int xx,node*f){
            node*p=&ap[xx];
            p->lch=p->rch=nil,p->prt=f,p->val=w[xx],p->xh=xx,p->siz=1;
            return p;
        }
        #define root(x) rt[us.find(x)]
        inline int son(node*x){return x==x->prt->rch;}
        inline void conn(node*x,node*y,int k){x->prt=y,y->ch[k]=x;}
        inline void rotate(node*x){
            node*f=x->prt,*g=f->prt,*&r=root(f->xh);
            int k=son(x),kk=son(f);
            conn(x->ch[k^1],f,k),conn(f,x,k^1);
            if(g==nil)r=x,r->prt=nil;else conn(x,g,kk);
            f->up(),x->up();
        }
        inline void splay(node*x,node*y=nil){
            while(x->prt!=y){
                node*f=x->prt;
                if(f->prt==y)return rotate(x);
                if(son(x)^son(f))rotate(x),rotate(x);
                else rotate(f),rotate(x);
            }
        }
        inline void merge(int x,int y){
            if(us.siz[x]>us.siz[y])swap(x,y);
            node*r=root(x);us.merge(x,y);
            dfs(r,y);
        }
        inline void dfs(node*x,int y){
    
            if(x->lch!=nil)dfs(x->lch,y),x->lch=nil;
            node*kk=x->rch;
            x->rch=nil,insert(x,y);
            if(kk!=nil)dfs(kk,y);
        }
        inline void insert(node*x,int y){
            node*p=root(y);
            while(1){
                ++p->siz;
                node*&nxt=p->ch[p->val<x->val];
                if(nxt==nil)return nxt=x,nxt->prt=p,splay(nxt);
                p=nxt;
            }
        }
        inline int kth(int d,int x){
            node*p=root(d);
            while(1){
                int num=p->lch->siz;
                if(x==num+1)return splay(p),p->xh;
                if(x<=num)p=p->lch;
                else p=p->rch,x-=num+1;
            }
        }
    }sp;
    #undef lch
    #undef rch
    #undef root
    int main(){
        scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",w+i);
        us.init(),sp.init();
        for(int i=1,u,v;i<=m;++i){scanf("%d%d",&u,&v),u=us.find(u),v=us.find(v);if(u==v)continue;sp.merge(u,v);}
        scanf("%d",&q);
        while(q--){
            char o[3];int x,y;scanf("%s%d%d",o,&x,&y);
            if(o[0]=='Q'){
                x=us.find(x);
                if(us.siz[x]<y){puts("-1");continue;}
                printf("%d
    ",sp.kth(x,y));
            }else if(o[0]=='B'){
                x=us.find(x),y=us.find(y);
                if(x!=y)sp.merge(x,y);
            }
        }
        return 0;
    }
    
    
    
    //对拍 这数据略有些不好造
    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    #define forg(i,x) for(int i=first[x];i;i=nxt[i])
    #define uu unsigned
    #define fi first
    #define se second
    #define ran() ((unsigned)rand())
    #define lam(z,k) [&](const z &a,const z &b){ return k; }
    #define od(x) ((x)&1)
    #define ev(x) (od(x)^1)
    #define scanf a1234=scanf
    #define system a1234=system
    #define fp fprintf
    int a1234;
    inline void xxx(){for(;;);}
    inline int rd(int l,int r){return rand()%(r-l+1)+l;}
    inline int rd1(int l,int r){--r;return rand()%(r-l+1)+l;}
    FILE* fo;
    const int mxn=1e5+3;
    int n;
    typedef vector<int>::iterator vit;
    class unio{
        public:
        int fa[mxn],siz[mxn],cnt;
        vector<int>cx;
        inline void init(){
            cnt=n;cx=vector<int>();
            for(int i=1;i<=n;++i)fa[i]=i,siz[i]=1,cx.push_back(i);
        }
        inline int find(int x){
            while(x!=fa[x])x=fa[x]=fa[fa[x]];
            return x;
        }
        inline void merge(int x,int y){
            x=find(x),y=find(y);fa[x]=y,siz[y]+=siz[x];
            --cnt,er(x);
        }
        inline void er(int x){
            cx.erase(lower_bound(cx.begin(),cx.end(),x));
        }
        inline int getan(int x){
            er(x);
            int res=cx[rd1(0,cx.size())];
            cx.insert(lower_bound(cx.begin(),cx.end(),x),x);
            return res;
        }
    }us;
    
    int w[mxn];
    inline void maked(){
        fo=fopen("te.in","w");
        n=rd(1,10000);
        us.init();
        fp(fo,"%d 0
    ",n);
        for(int i=1;i<=n;++i)w[i]=i;
        random_shuffle(w+1,w+n+1);
        for(int i=1;i<=n;++i)fp(fo,"%d ",w[i]);
        fp(fo,"
    ");
        int q=rd(1,10000);fp(fo,"%d
    ",q);
        for(int i=1;i<=q;++i){
            if(us.cnt>1&&rand()%3){
                int xx=rd(1,n),x=us.find(xx),y=us.getan(x);
                fp(fo,"B %d %d
    ",xx,y);
                us.merge(x,y);
                continue;
            }
            int x=rd(1,n),y=rd(1,us.siz[us.find(x)]);
            fp(fo,"Q %d %d
    ",x,y);
        }
        puts("ok");
        fclose(fo);
    }
    inline int work(){
        maked();
        system("./a <te.in >1.ans");
        system("./b <te.in >2.ans");
        return system("diff 1.ans 2.ans -b -B -q");
    }
    int main(){
        srand((uu)time(0));
    //    maked();return system("cat te.in"),3;
        system("g++ ac.cpp -O2 -Wall -o a");
        system("g++ yx.cpp -O2 -Wall -o b");
        int cases=0;
        for(;;){printf("%d
    ",++cases);if(work())return 3;if(cases==1000)return 0;}
        return 0;
    }
    
  • 相关阅读:
    资深工程师为何否定这种单例模式
    C#经典面试题及答案【20090210更新】
    难道SQL的子查询就是鸡肋吗?
    转:WCF基础知识问与答
    针对分析单点登录(流程图与数据安全)提出的问题及解决方案
    老生常谈:装饰者模式
    我对IDisposable接口的理解
    log4net日志组件经验分享
    老生常谈:工厂模式兄弟姐妹
    探讨高访问量网站优化方案(从图片角度)
  • 原文地址:https://www.cnblogs.com/happyguy/p/13740290.html
Copyright © 2011-2022 走看看