zoukankan      html  css  js  c++  java
  • BZOJ_2161_布娃娃_权值线段树

    BZOJ_2161_布娃娃_权值线段树

    Description

    小时候的雨荨非常听话,是父母眼中的好孩子。在学校是老师的左右手,同学的好榜样。后来她成为艾利斯顿第二
    代考神,这和小时候培养的良好素质是分不开的。雨荨的妈妈也为有这么一个懂事的女儿感到高兴。一次期末考试
    ,雨荨不知道第多少次,再次考了全年级第一名。雨荨的妈妈看到女儿100分的成绩单时,脸上又泛起了幸福的笑
    容,作为奖励,她给雨荨买了n个布娃娃。细心的雨荨发现,第i个布娃娃有一个耐心值P[i]以及一个魅力值C[i],
    并且还有能够忍受的耐心值的上限R[i]以及下限L[i]。当一个布娃娃j满足L[j]<=P[i]并且P[i]<=R[j],那么布娃
    娃j喜欢布娃娃i。雨荨还发现,一个布娃娃有可能喜欢它自己。每个布娃娃心中都有一个谜团,具体来说就是:第
    i个布娃娃想知道喜欢它的布娃娃中,魅力值第i大的布娃娃的魅力值是多少,并且称这个布娃娃的谜团答案为这个
    魅力值的大小,如果不存在,那么这个布娃娃的谜团答案为0。鉴于雨荨的上司栋栋不让题目的数据过大,下面给
    出数据的生成方法:给出16个参数:
    Padd, Pfirst, Pmod, Pprod, Cadd, Cfirst, Cmod, Cprod, Ladd, Lfirst, Lmod, Lprod, Radd, Rfirst, Rmod, Rprod。
    ----------------------------------------------------------------------------------------
    P[1] = Pfirst % Pmod, P[i] = (P[i-1]   Pprod + Padd + i) % Pmod (i > 1)。
    ----------------------------------------------------------------------------------------
    对于C、L、R数组也有类似的得到方式, %代表取余运算。注意:L和R数组生成完之后,如果某个布娃娃的忍耐度上
    限小于下限,那么交换它的上限和下限。当然,雨荨也不会让你告诉她每个布娃娃的谜团答案,因为那样会使输出
    数据很大。所以雨荨希望你告诉她,所有布娃娃谜团答案的和除以19921228的余数是多少。

    Input

    输入的第一行有一个整数n,代表布娃娃的个数。
    输入的第二行有16个用空格隔开的整数
    分别代表Padd,Pfirst,Pmod,Pprod,Cadd,Cfirst,Cmod,Cprod,Ladd,Lfirst,Lmod,Lprod,Radd,Rfirst,Rmod,Rprod。
    16个参数均为1到100,000,000中的整数。

    Output

    输出一个整数,代表所有布娃娃谜团答案的和除以19921228的余数。

    Sample Input

    3
    2 3 4 3 1 4 5 2 3 6 9 1 1 2 3 4

    Sample Output

    4

    先离线下来,然后用类似树状数组二维数点的方式把每个布娃娃拆成两个,一个在L处加,一个在R+1处减。
    放在一起排序,然后查询时权值线段树上二分即可。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 200050
    #define maxn 100000000
    int t[N*35],ls[N*35],rs[N*35],cnt,n,ans,tot;
    struct A {
        int l,r,p,c;
    }a[N];
    struct P {
        int p,flg,id;
        P() {}
        P(int p_,int f_,int id_) :
            p(p_),flg(f_),id(id_) {}
    }d[N<<1];
    bool cmp(const P &x,const P &y) {
        if(x.p==y.p) return x.flg<y.flg;
        return x.p<y.p;
    }
    void update(int l,int r,int x,int v,int &p) {
        if(!p) p=++tot;
        t[p]+=v; 
        if(l==r) return ;
        int mid=(l+r)>>1;
        if(x<=mid) update(l,mid,x,v,ls[p]);
        else update(mid+1,r,x,v,rs[p]);
    }
    int qk(int l,int r,int k,int p) {
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(k<=t[ls[p]]) return qk(l,mid,k,ls[p]);
        else return qk(mid+1,r,k-t[ls[p]],rs[p]);
    }
    int main() {
        int pad,pfi,pmod,prd,cad,cfi,cmod,crd,lad,lfi,lmod,lrd,rad,rfi,rmod,rrd;
        register int i;
        scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",&n,&pad,&pfi,&pmod,&prd,&cad,&cfi,&cmod,&crd,&lad,&lfi,&lmod,&lrd,&rad,&rfi,&rmod,&rrd);
        a[1].p=pfi%pmod;
        a[1].c=cfi%cmod;
        a[1].l=lfi%lmod;
        a[1].r=rfi%rmod;
        // if(a[1].l>a[1].r) swap(a[1].l,a[1].r);
        // d[++cnt]=P(a[1].l,1,1);
        // d[++cnt]=P(a[1].r+1,2,1);
        // d[++cnt]=P(a[1].p,3,1);
        // printf("i=%d, l=%d r=%d p=%d c=%d
    ",1,a[1].l,a[1].r,a[1].p,a[1].c);
        for(i=2;i<=n;i++) {
            a[i].p=(1ll*a[i-1].p*prd+pad+i)%pmod;
            a[i].c=(1ll*a[i-1].c*crd+cad+i)%cmod;
            a[i].l=(1ll*a[i-1].l*lrd+lad+i)%lmod;
            a[i].r=(1ll*a[i-1].r*rrd+rad+i)%rmod;
            // if(a[i].l>a[i].r) swap(a[i].l,a[i].r);
            // printf("i=%d, l=%d r=%d p=%d c=%d
    ",i,a[i].l,a[i].r,a[i].p,a[i].c);
            // d[++cnt]=P(a[i].l,1,i);
            // d[++cnt]=P(a[i].r+1,2,i);
            // d[++cnt]=P(a[i].p,3,i);
        }
        for(i=1;i<=n;i++) {
            if(a[i].l>a[i].r) swap(a[i].l,a[i].r);
            d[++cnt]=P(a[i].l,1,i);
            d[++cnt]=P(a[i].r+1,2,i);
            d[++cnt]=P(a[i].p,3,i);
        }
        // puts("-----------------------------------");
        int now=0,root=0;
        sort(d+1,d+cnt+1,cmp);
        for(i=1;i<=cnt;i++) {
            // printf("i=%d, p=%d flg=%d id=%d
    ",i,d[i].p,d[i].flg,d[i].id);
            if(d[i].flg==1) {
                now++;
                update(0,maxn,a[d[i].id].c,1,root);
            }else if(d[i].flg==2) {
                now--;
                update(0,maxn,a[d[i].id].c,-1,root);
            }else {
                if(now>=d[i].id) {
                    (ans+=qk(0,maxn,now-d[i].id+1,root))%=19921228;
                }
            }
        }
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    地铁结队开发(一)
    构建之法(一)——软件工程师的成长
    第二周学习总结
    新的开始
    开学第一周作业
    第一周学习总结
    软件工程第六周总结
    软件工程第五周总结
    清明节第三天
    清明节第二天
  • 原文地址:https://www.cnblogs.com/suika/p/9062538.html
Copyright © 2011-2022 走看看