「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\n",ans);
147     return 0;
148 }
View Code

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

posted @ 2017-12-28 22:09  Blue233333  阅读(277)  评论(0编辑  收藏  举报