ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

带修改,询问区间内出现次数大于区间长度一半的数个数,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

 

posted on 2017-08-09 10:18  nul  阅读(281)  评论(0编辑  收藏  举报