zoukankan      html  css  js  c++  java
  • luogu P5338 [TJOI2019]甲苯先生的滚榜

    传送门

    首先,排名系统,一看就知道是原题,可以上平衡树来维护

    然后考虑一种比较朴素的想法,因为我们要知道排名在一个人前面的人数,也就是AC数比他多的人数+AC数一样并且罚时少的人数,所以考虑维护那两个东西.AC数更多的人数显然可以直接上树状数组.后者的话可以对每一种AC数开值域线段树,存每个罚时有多少人,注意到罚时之和不会超过(1.5*10^6),所以动态开点线段树可以轻松解决.然后每次有个人AC数和罚时改变就先在原来的位置-1,然后在新位置+1.每次询问就是树状数组上AC数(>)当前AC数的对应区间之和(+)对应线段树上罚时(<)当前罚时的区间之和

    // luogu-judger-enable-o2
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    #define ui unsigned int
    
    using namespace std;
    const int N=1e5+10,M=1e6+10,MX=1500000;
    LL rd()
    {
        LL x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    ui randNum(ui& seed ,ui last,const ui m)
    { 
        seed=seed*17+last;
        return seed%m+1; 
    }
    ui sd;
    int m,n,a[N],b[N],c[M];
    void ad(int x,int y){while(x<=n) c[x]+=y,x+=x&(-x);}
    int gsm(int x){int an=0;while(x) an+=c[x],x-=x&(-x);return an;}
    int s[M*25],ch[M*25][2],rt[M],tt;
    void add(int o1,int o2,int x)
    {
        int l=1,r=MX;
        s[o1]=s[o2]+1;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(x<=mid)
            {
                ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
                o1=ch[o1][0],o2=ch[o2][0];
                r=mid;
            }
            else
            {
                ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
                o1=ch[o1][1],o2=ch[o2][1];
                l=mid+1;
            }
            s[o1]=s[o2]+1;
        }
    }
    void dec(int o,int x)
    {
        int l=1,r=MX;
        --s[o];
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(x<=mid) o=ch[o][0],r=mid;
            else o=ch[o][1],l=mid+1;
            --s[o];
        }
    }
    int quer(int o,int l,int r,int ll,int rr)
    {
        if(ll>rr||!o) return 0;
        if(ll<=l&&r<=rr) return s[o];
        int an=0,mid=(l+r)>>1;
        if(ll<=mid) an+=quer(ch[o][0],l,mid,ll,rr);
        if(rr>mid) an+=quer(ch[o][1],mid+1,r,ll,rr);
        return an;
    }
        
    
    int main()
    {
        int T=rd(),ans=7;
        while(T--)
        {
            m=rd(),n=rd(),sd=rd();
            for(int i=1;i<=n;++i) c[i]=rt[i]=0;
            for(int i=1;i<=m;++i) a[i]=b[i]=0;
            tt=0;
            for(int i=1;i<=n;++i)
            {
                int x=randNum(sd,ans,m),y=randNum(sd,ans,m);
                if(a[x]) dec(rt[a[x]],b[x]),ad(a[x],-1);
                ++a[x],b[x]+=y;
                int las=rt[a[x]];
                add(rt[a[x]]=++tt,las,b[x]),ad(a[x],1);
                ans=gsm(n)-gsm(a[x])+quer(rt[a[x]],1,MX,1,b[x]-1);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Oracle列转行函数Listagg以及pivot查询示例
    Java执行操作系统命令
    JUnit学习之hamcrest、testSuite介绍及测试原则
    JUnit学习之JUnit的基本介绍
    Oracle笔记-Multitable INSERT 的用法
    Oracle 11g 新特性 --SQL Plan Management 说明
    Java习惯用法总结
    将Eclipse的Java Project转换为Dynamic Web Project
    在Eclipse中调试web项目
    在Eclipse中添加Servlet-api.jar的方法
  • 原文地址:https://www.cnblogs.com/smyjr/p/10841151.html
Copyright © 2011-2022 走看看