zoukankan      html  css  js  c++  java
  • bzoj5110: [CodePlus2017]Yazid 的新生舞会

    Description

    Yazid有一个长度为n的序列A,下标从1至n。显然地,这个序列共有n(n+1)/2个子区间。对于任意一个子区间[l,r]
    ,如果该子区间内的众数在该子区间的出现次数严格大于(r-l+1)/2(即该子区间长度的一半),那么Yazid就说这
    个子区间是"新生舞会的"。所谓众数,即为该子区间内出现次数最多的数。特别地,如果出现次数最多的数有多个
    ,我们规定值最小的数为众数。现在,Yazid想知道,共有多少个子区间是"新生舞会的"

    Input

    第一行2个用空格隔开的非负整数n,type,表示序列的长度和数据类型。数据类型的作用将在子任务中说明。
    第二行n个用空格隔开的非负整数,依次为A1,A2,...,An,描述这个序列。
    N<=500000,0<=Type<=3
    对于所有数据,保证 0 ≤ Ai ≤ n - 1。
    对于 type = 0 的数据,没有任何特殊约定。
    对于 type = 1 的数据,保证 Ai ∈ {0, 1}。
    对于 type = 2 的数据,保证序列 A 的众数在整个序列中的出现次数不超过 15。
    对于 type = 3 的数据,保证 Ai ≤ 7。

    Output

    输出一行一个整数,表示答案。

    枚举众数的值a,一个区间(L,R]符合条件,当且仅当F(R)-F(L)>0,其中F(x)=2*([1,x]中a的个数)-x。

    从左到右扫描x=1..n,插入F(x),查询F(<x)的和

    F(x)在跨过a的出现位置时发生突变,其余时候x每+1,F(x)就-1,因此可以批量处理,每次插入和查询一个区间,算一下贡献可以转为区间加二次函数,单点查询,可以用树状数组维护

    时间复杂度O(nlogn)

    #include<bits/stdc++.h>
    typedef long long i64;
    const int N=5e5+77;
    char ib[N*12],*ip=ib;
    int _(){int x;scanf("%d",&x);return x;}
    i64 ans=0;
    int n,mx;
    struct pos{
        int x,y;
    }ps[N],pb[N];
    void rsort(pos*a,pos*b,int n){
        for(int t=0;t<20;t+=10){
            int ts[1111]={};
            pos*rs[1111],*p=b;
            for(int i=0;i<n;++i)++ts[a[i].y>>t&1023];
            for(int i=0;i<1024;++i)rs[i]=p,p+=ts[i];
            for(int i=0;i<n;++i)*rs[a[i].y>>t&1023]++=a[i];
            std::swap(a,b);
        }
    }
    int tk;
    struct node{
        i64 s0,s1,s2;
        int ed;
    }bit[N*2];
    void inc(int w,int a){
        w+=n+2;
        i64 a0=a*w*i64(w-1),a1=a*i64(1-w*2),a2=a;
        for(;w<=mx;w+=w&-w){
            if(bit[w].ed!=tk){
                bit[w]=(node){a0,a1,a2,tk};
            }else{
                bit[w].s0+=a0;
                bit[w].s1+=a1;
                bit[w].s2+=a2;
            }
        }
    }
    i64 sum(int w){
        w+=n+2;
        int w0=w;
        i64 s0=0,s1=0,s2=0;
        for(;w;w-=w&-w)if(bit[w].ed==tk){
            s0+=bit[w].s0;
            s1+=bit[w].s1;
            s2+=bit[w].s2;
        }
        return (s2*w0+s1)*w0+s0;
    }
    void ins(int l,int r,int c){
        inc(2*c-r+1,1);
        inc(2*c-l+1,-1);
    }
    void que(int l,int r,int c){
        ans+=sum(2*c-l)-sum(2*c-r);
    }
    void cal(pos*a,int n){
        ++tk;
        ins(0,a[1].x,0);
        for(int i=1;i<n;++i){
            int w=a[i].x;
            que(a[i].x,a[i+1].x,i);
            ins(a[i].x,a[i+1].x,i);
        }
        que(a[n].x,::n+1,n);
    }
    int main(){
        n=_();_();
        mx=n*2+5;
        for(int i=1;i<=n;++i)ps[i]=(pos){i,_()};
        rsort(ps+1,pb,n);
        for(int i=1,j=1;i<=n;i=j){
            for(++j;j<=n&&ps[i].y==ps[j].y;++j);
            cal(ps+i-1,j-i);
        }
        printf("%lld
    ",ans/2);
        return 0;
    }
  • 相关阅读:
    Epoll技术深入学习
    nginx
    epoll案例
    Linux网络编程初步
    链表快速排序(已通过ACM在线评测)
    C++内存管理
    c++11并发语法初步
    数据库与SQL优化笔记(一)
    C++面向对象模型(虚表与虚表指针)
    c++的一些杂项
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7907026.html
Copyright © 2011-2022 走看看