洛谷3765总统选举暨洛谷5月月赛R1B题

来源:互联网 发布:用淘宝充话费怎么退款 编辑:程序博客网 时间:2024/05/21 13:56

传送门
这题我考场上花了大量时间思考与打代码,最后应该是花费4小时得到70分(乐多赛制罚成57分),太浪费时间了,一定是因为我太弱了。
我已开始的想法是对于每个询问区间,在区间里随机选很多次数,统计一下每个数的出现次数是否满足条件即可。但是,随机数不是很稳定,万一区间长度10000,有5100个1,4900个2,然后发现100次随机,有49次是2,51次是1,不就gg了?
于是,我决定,每次询问随机A次,如果一个数在A次随机中出现超过B次,那么强行用数据结构(具体地说,我赛场上是对每种数x,建立一颗权值线段树,对于每一位,若等于x,权值赋成1,否则赋成0)统计一下这个数在区间中出现次数是否超过区间长度的一半即可。
一开始我取A=30,B=10,然后是50分。
后来我把B改成7,是70分。
然后就不敢改了。
比赛结束后,我把B改成5,90分,被卡常。再把用的数据结构从动态开点权值线段树变成treap,每次查lr+1的rank就AC了。这可能是因为权值线段树的区间范围是死的1到n,treap的节点数却不是。
但是,哪位大佬能解释一下,为什么参数的调整这么玄学?(辣鸡rand()还我血汗分)

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<queue>#include<set>#include<map>#include<vector>#include<list>#include<fstream>#include<cmath>#include<cctype>#include<stack>#include<cstdlib>#include<ctime>using namespace std;typedef long long ll;typedef unsigned int ui;inline int getint(){    int x=0;    char c=getchar();    while(!isdigit(c))c=getchar();    for(;isdigit(c);c=getchar())x=x*10+c-48;    return x;}int buf[10];inline void putint(int x){    int xb=0;    for(;x;x/=10)buf[++xb]=x%10;    for(;xb;--xb)putchar(buf[xb]+48);}const int N=500010,maxn=6000000,K=N<<1;class treap{    private:        struct node{            node *l,*r;            int p,size,w;            int v;//kg            node(int _v):v(_v){                l=r=NULL;                p=rand();                w=size=1;            }            void maintain(){                size=w;                if(l!=NULL)size+=l->size;                if(r!=NULL)size+=r->size;            }        };        node*head;        void lturn(node* &x){            node*t=x->r;            x->r=t->l;            t->l=x;            x->maintain();            t->maintain();            x=t;        }        void rturn(node* &x){            node*t=x->l;            x->l=t->r;            t->r=x;            x->maintain();            t->maintain();            x=t;        }        void ins(node* &o,int y){            if(o==NULL)o=new node(y);                else if(y>o->v){                    ins(o->r,y);                    if(o->r->p>o->p)lturn(o);                }else if(y<o->v){                    ins(o->l,y);                    if(o->l->p>o->p)rturn(o);                }else ++o->w;            o->maintain();        }           void del(node* &x,int y){            if(x==NULL)return;            if(y>x->v)del(x->r,y);                else if(y<x->v)del(x->l,y);                    else{                        if(x->w>1){                            --x->size;                            --x->w;                            return;                        }                        if(x->l==NULL){                            node*z=x;                            x=x->r;                            delete z;                            return;                        }                        if(x->r==NULL){                            node*z=x;                            x=x->l;                            delete z;                            return;                        }                        if(x->l->p>x->r->p){                                                                    rturn(x);                            del(x->r,y);                        }else{                            lturn(x);                            del(x->l,y);                        }                    }            if(x!=NULL)--x->size;        }     public:        void insert(int x){            ins(head,x);        }        void erase(int x){            del(head,x);        }        int rank(int y){            node*x=head;            int ans=0;            while(x!=NULL){                int s=0;                if(x->l!=NULL)s=x->l->size;                if(y==x->v)return ans+s+1;                if(y>x->v){                    ans+=s+x->w;                    x=x->r;                }else x=x->l;            }            return ans+1;        }        int lessnum(int y){            return rank(y)-1;        }        int morenum(int y){            node*x=head;            int ans=0;            while(x!=NULL){                int s=0;                if(x->r!=NULL)s=x->r->size;                if(y==x->v)return ans+s;                if(y<x->v){                    ans+=s+x->w;                    x=x->l;                }else x=x->r;            }            return ans;        }        int kth(int y){            node*x=head;            for(;;){                int u=0,v=x->w;                if(x->l!=NULL)u=x->l->size;                if(u<y && u+v>=y)return x->v;                if(y>u+v){                    x=x->r;                    y-=u+v;                }else x=x->l;            }        }        int prev(int y){            node*x=head,*t=NULL;            while(x!=NULL){                if(x->v>=y)x=x->l;                    else{                        t=x;                        x=x->r;                    }            }                 if(t==NULL)return -(1<<30);                else return t->v;        }         int succ(int y){             node*x=head,*t=NULL;             while(x!=NULL){                 if(x->v<=y)x=x->r;                     else{                         t=x;                         x=x->l;                     }             }             if(t==NULL)return 1<<30;                 else return t->v;         }         int size(){             return head->size;         }         bool find(int y){             node*x=head;             for(;x!=NULL &&x->v!=y;y>x->v?x=x->r:x=x->l);             return x!=NULL;         }}t[N];int n,i,m,rt[N],l,r,s,k,b[K],c[N],x,d[N],e[10],j,len,f[K];int main(){    n=getint();    m=getint();    for(i=1;i<=n;++i){        d[i]=getint();        t[d[i]].insert(i);    }    srand(time(0));    while(m--){        l=getint();        r=getint();        s=getint();        k=getint();        for(i=1;i<=k;++i)f[i]=getint();        j=0;        len=r-l+1;        for(i=1;i<=30;++i){            c[i]=rand()%len+l;            ++b[d[c[i]]];        }        for(i=1;i<=30;++i){            if(b[d[c[i]]]>5)e[++j]=d[c[i]];            b[d[c[i]]]=0;        }        for(i=1;i<=j;++i)            if(t[e[i]].rank(r+1)-t[e[i]].rank(l)>len>>1)break;        if(j && i<=j)x=e[i];            else x=s;        putint(x);        putchar('\n');        for(i=1;i<=k;++i){            t[d[f[i]]].erase(f[i]);            d[f[i]]=x;            t[d[f[i]]].insert(f[i]);        }    }    for(i=1;i<=30;++i){        c[i]=rand()%n+1;        ++b[d[c[i]]];    }    for(i=1;i<=30;++i){        if(b[d[c[i]]]>5)e[++j]=d[c[i]];        b[d[c[i]]]=0;    }    for(i=1;i<=j;++i)if(t[e[i]].rank(r+1)-t[e[i]].rank(l)>n>>1)break;    if(j && i<=j)printf("%d\n",e[i]);        else puts("-1");    return 0;}
0 0
原创粉丝点击