zoukankan      html  css  js  c++  java
  • 「CodePlus 2017 11 月赛」Yazid 的新生舞会

    n<=500000的数字,问有多少个区间的众数出现次数严格大于区间长度的一半。

    这么说来一个区间就一个众数了,所以第一反应是枚举数字,对下标进行处理。然后没有第二反应。很好。

    在枚举一个数字的时候,可以把这个数字出现的位置记+1,没出现的位置记-1,实际就是问现在这个数组有多少个区间和>0,就是问对每个前缀和Si有多少Sj<Si。

    出现的位置加起来总共只有n个,如果-1的那些区间能够进行区间处理该多好啊!

    那就维护一个以Si的值为下标的东西,然后查一个区间的答案就是查:

    红色部分。也就是要查一个区间和乘上若干,以及一个区间每个数乘上等差数列。可以通过维护每个Si的值的个数的区间和,以及区间Cnt_i * i的和。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<algorithm>
      4 #include<stdlib.h>
      5 //#include<bitset>
      6 #include<queue>
      7 //#include<math.h>
      8 //#include<time.h>
      9 //#include<iostream>
     10 using namespace std;
     11 
     12 int n,type;
     13 #define maxn 1000011
     14 #define LL long long
     15 struct Node
     16 {
     17     int id,v;
     18     bool operator < (const Node &b) const {return v<b.v || (v==b.v && id<b.id);}
     19 }a[maxn];
     20 int lisan[maxn],li=0;
     21 
     22 const int most=1000006;
     23 struct SMT
     24 {
     25     struct Node
     26     {
     27         int ls,rs;
     28         int sum;LL sss;
     29         int add;
     30     }a[maxn<<1];
     31     int size,root;
     32     void clear() {size=root=0;}
     33     int ql,qr,v;
     34     void up(int x)
     35     {
     36         const int &p=a[x].ls,&q=a[x].rs;
     37         a[x].sum=a[p].sum+a[q].sum;
     38         a[x].sss=a[p].sss+a[q].sss;
     39     }
     40     void New(int &x)
     41     {
     42         x=++size;  a[x].ls=a[x].rs=0;
     43         a[x].sss=a[x].add=a[x].sum=0;
     44     }
     45     void addsingle(int x,int L,int R,int v)
     46     {
     47         a[x].sum+=(R-L+1)*v;
     48         a[x].sss+=((1ll*(most-R+1+most-L+1)*(R-L+1))>>1)*v;
     49         a[x].add+=v;
     50     }
     51     void down(int x,int L,int R)
     52     {
     53         int &p=a[x].ls,&q=a[x].rs,mid=(L+R)>>1;
     54         if (!p) New(p); if (!q) New(q);
     55         if (a[x].add)
     56         {
     57             addsingle(p,L,mid+0,a[x].add);
     58             addsingle(q,mid+1,R,a[x].add);
     59             a[x].add=0;
     60         }
     61     }
     62     void Add(int &x,int L,int R)
     63     {
     64         if (!x) New(x);
     65         if (ql<=L && R<=qr) {addsingle(x,L,R,v); return;}
     66         down(x,L,R);
     67         const int mid=(L+R)>>1;
     68         if (ql<=mid) Add(a[x].ls,L,0+mid);
     69         if (qr> mid) Add(a[x].rs,mid+1,R);
     70         up(x);
     71     }
     72     void add(int L,int R,int v)
     73     {
     74         if (L>R) return;
     75         L+=most>>1; R+=most>>1;
     76         this->v=v; ql=L; qr=R;
     77         Add(root,1,most);
     78     }
     79     LL Querysum(int &x,int L,int R)
     80     {
     81         if (!x) New(x);
     82         if (ql<=L && R<=qr) return a[x].sum;
     83         down(x,L,R);
     84         const int mid=(L+R)>>1; LL ans=0;
     85         if (ql<=mid) ans+=Querysum(a[x].ls,L,mid);
     86         if (qr> mid) ans+=Querysum(a[x].rs,mid+1,R);
     87         return ans;
     88     }
     89     LL querysum(int L,int R)
     90     {
     91         if (L>R) return 0;
     92         L+=most>>1; R+=most>>1;
     93         ql=L; qr=R;
     94         return Querysum(root,1,most);
     95     }
     96     LL Querysss(int &x,int L,int R)
     97     {
     98         if (!x) New(x);
     99         if (ql<=L && R<=qr) return a[x].sss;
    100         down(x,L,R);
    101         const int mid=(L+R)>>1; LL ans=0;
    102         if (ql<=mid) ans+=Querysss(a[x].ls,L,mid);
    103         if (qr> mid) ans+=Querysss(a[x].rs,mid+1,R);
    104         return ans;
    105     }
    106     LL querysss(int L,int R)
    107     {
    108         if (L>R) return 0;
    109         L+=most>>1; R+=most>>1;
    110         ql=L; qr=R;
    111         return Querysss(root,1,most);
    112     }
    113 }t;
    114 
    115 int main()
    116 {
    117     scanf("%d%d",&n,&type);
    118     for (int i=1;i<=n;i++) scanf("%d",&a[i].v),a[i].id=i;
    119     sort(a+1,a+1+n); a[n+1].v=0x3f3f3f3f;
    120     
    121     LL ans=0;
    122     for (int i=2,j=1;i<=n+1;i++) if (a[i].v!=a[i-1].v)
    123     {
    124         t.clear();
    125         int last=0,where=0;
    126         t.add(0,0,1);
    127         for (;j<i;j++)
    128         {
    129             const int now=a[j].id;
    130             if (now-last>1)
    131             {
    132                 int len=now-last-1;
    133                 ans+=t.querysss(where-len-1,where-2)+t.querysum(1-(most>>1),where-len-2)*len
    134                 -t.querysum(where-len-1,where-2)*(most-where-(most>>1)+2);
    135                 t.add(where-len,where-1,1);
    136                 where-=len;
    137             }
    138             ans+=t.querysum(1-(most>>1),where);
    139             where++; t.add(where,where,1);
    140             last=now;
    141         }
    142         int len=n-last;
    143         (len)&&(ans+=t.querysss(where-len-1,where-2)+t.querysum(1-(most>>1),where-len-2)*len
    144         -t.querysum(where-len-1,where-2)*(most-where-(most>>1)+2));
    145     }
    146     printf("%lld
    ",ans);
    147     return 0;
    148 }
    View Code

    这题还有树状数组和分治的写法。待填坑。

  • 相关阅读:
    hdu 携程全球数据中心建设 (球面距离 + 最小生成树)
    next_permutation()函数 和 prev_permutation() 按字典序求全排列
    poj 3792 Area of Polycubes (简单模拟)
    poj 3790 Recursively Palindromic Partitions (递推)
    hdu 1575 Tr A (矩阵快速幂入门题)
    hdu 2986 Ballot evaluation (模拟)
    sscanf() 和 sprintf()的用法。
    Codeforces Round #239 (Div. 2)
    hdu 2372 El Dorado (dp)
    hdu 3433 A Task Process(dp+二分)
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8137993.html
Copyright © 2011-2022 走看看