• bzoj4966: 总统选举


    带修改,询问区间内出现次数大于区间长度一半的数个数,N,Q<=500000

    如果一个数在一个区间内出现次数大于一半,那么在区间内随机抽一些数,抽到这个数的个数通常会很多,因此可以用平衡树维护每个权值的出现位置,只查询在抽查中出现次数充分多的数

    具体的,最坏情况下一个数在区间内出现次数为1/2区间长度,此时抽取100个数,这个数的出现次数<=25的概率为$10^-7$数量级,可以作为判定标准

    #include<bits/stdc++.h>
    const int RN=100000;
    char buf[RN],*ptr=buf+RN,ob[RN],*op=ob;
    int G(){
        if(ptr-buf==RN)fread(ptr=buf,1,RN,stdin);
        return *ptr++;
    }
    int _(){
        int x=0;
        if(ptr<buf+RN-100){
            while(*ptr<48)++ptr;
            while(*ptr>47)x=x*10+*ptr++-48;
        }else{
            int c=G();
            while(c<48)c=G();
            while(c>47)x=x*10+c-48,c=G();
        }
        return x;
    }
    #define fl fwrite(ob,1,op-ob,stdout),op=ob
    void pr(int x){
        if(op>ob+RN-100)fl;
        if(x<0)x=-x,*op++='-';
        int ss[15],sp=0;
        do ss[++sp]=x%10;while(x/=10);
        while(sp)*op++=ss[sp--]+48;
        *op++=10;
    }
    const int N=500007;
    int n,m,a[N];
    struct node{
        node*c[2];
        int rnd,sz;
        void sp(node*x,node*&l,node*&r);
    }ns[N],*rt[N];
    void node::sp(node*x,node*&l,node*&r){
        if(this==ns){l=r=ns;return;}
        if(x<this){
            r=this;
            c[0]->sp(x,l,c[0]);
            sz-=l->sz;
        }else{
            l=this;
            c[1]->sp(x,c[1],r);
            sz-=r->sz;
        }
    }
    node*mg(node*a,node*b){
        if(a==ns)return b;
        if(b==ns)return a;
        if(a->rnd>b->rnd){
            a->sz+=b->sz;
            a->c[1]=mg(a->c[1],b);
            return a;
        }
        b->sz+=a->sz;
        b->c[0]=mg(a,b->c[0]);
        return b;
    }
    #define _w (*w)
    void ins(node**w,node*x){
        while(x->rnd<_w->rnd)++_w->sz,w=_w->c+(_w<x);
        x->sz=1+_w->sz;
        _w->sp(x,x->c[0],x->c[1]);
        _w=x;
    }
    void del(node**w,node*x){
        while(_w!=x)--_w->sz,w=_w->c+(_w<x);
        x->sz=1;
        _w=mg(x->c[0],x->c[1]);
        x->c[0]=x->c[1]=ns;
    }
    #undef _w
    int seed=0;
    int rnd(){
        return seed=(seed*141+29399)%13999133;
    }
    int leq(int p,node*x){
        int s=0;
        for(node*a=rt[p];a!=ns;){
            if(a<=x)s+=a->c[0]->sz+1,a=a->c[1];
            else a=a->c[0];
        }
        return s;
    }
    int ts[N],tk=0,xs[N],xp;
    int query(int L,int R,int v){
        ++tk;
        xp=0;
        for(int t=0;t<60;++t){
            int pos=L+rnd()%(R-L+1);
            int x=a[pos];
            if(!ts[x])xs[xp++]=x;
            ++ts[x];
            if(++pos>R)pos=L;
        }
        for(int i=0;i<xp;++i)if(ts[xs[i]]>10){
            int s=leq(xs[i],ns+R)-leq(xs[i],ns+L-1);
            if(s*2>R-L+1){
                v=xs[i];
                break;
            }
        }
        for(int i=0;i<xp;++i)ts[xs[i]]=0;
        return v;
    }
    int main(){
        n=_(),m=_();
        seed=n+m+1231^234;
        for(int i=1;i<=n;++i)rt[i]=ns;
        ns[0]=(node){ns,ns,-1,0};
        for(int i=1;i<=n;++i){
            ns[i]=(node){ns,ns,rnd(),1};
            a[i]=_();
            ins(rt+a[i],ns+i);
        }
        for(int i=1;i<=m;++i){
            int l=_(),r=_(),s=_(),k=_(),ans=query(l,r,s);
            for(int j=0,x;j<k;++j){
                x=_();
                if(a[x]!=ans){
                    del(rt+a[x],ns+x);
                    a[x]=ans;
                    ins(rt+a[x],ns+x);
                }
            }
            pr(ans);
        }
        pr(query(1,n,-1));
        return fl,0;
    }
    View Code
  • 相关阅读:
    Redis(二) 扩展
    Redis(一)基础
    Java垃圾回收机制 入门
    freeregex-0.01 使用文档
    上传文件到阿里云linux服务器
    jQuery代码解释(基本语法)
    JQuery中使用FormData异步提交数据和提交文件
    jQuery获取data-*属性值
    jquery 中 $.map 的使用方法
    mysql创建表时反引号的作用
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7323794.html
Copyright © 2020-2023  润新知