1686 第K大区间

时间限制:1 秒 空间限制:131072 KB
 

定义一个区间的值为其众数出现的次数
现给出n个数,求将所有区间的值排序后,第K大的值为多少。

众数(统计学/数学名词)_百度百科 

Input
第一行两个数n和k(1<=n<=100000,k<=n*(n-1)/2)
第二行n个数,0<=每个数<2^31
Output
一个数表示答案。
Input示例
4 2
1 2 3 2
Output示例
2
思路:二分答案t,统计众数出现次数大于等于t的区间有多少个。
枚举右端点R,计算左端点L最大为多少,使得区间[L,R]的值大于等于t,对于每个R他对答案贡献为L。
通过线性扫一遍找出每一个数的前面第t-1个与他相同的数字,记其位置为b[i],若不存在则为0。
若R增加,则[L,R+1]的值也必定大于等于t,所以新的L=max(L,b[R+1]),这样就可以找出每一个R对应的L,O(n)计算出答案。
总复杂度O(nlogn)
  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<queue>
  6 #include<stack>
  7 #include<map>
  8 #include<math.h>
  9 using namespace std;
 10 typedef long long LL;
 11 int id[100005];
 12 int cnt[100005];
 13 int cp[100005];
 14 int str[100005];
 15 LL tt[100005];
 16 typedef struct pp
 17 {
 18     LL x;
 19     int id;
 20 } ss;
 21 ss ans[100005];
 22 LL check(int mid);
 23 bool cmp(pp n,pp m)
 24 {
 25     return n.x<m.x;
 26 }
 27 LL n,m;
 28 int main(void)
 29 {
 30     int i,j,k;
 31     while(scanf("%lld %lld",&n,&m)!=EOF)
 32     {
 33         memset(cnt,0,sizeof(cnt));
 34         for(i=1; i<=n; i++)
 35         {
 36             scanf("%lld",&ans[i].x);
 37             ans[i].id=i;
 38         }
 39         LL nn=ans[1].x;
 40         int mm=1;
 41         sort(ans+1,ans+n+1,cmp);
 42         for(i=1; i<=n; i++)
 43         {
 44             if(ans[i].x!=nn)
 45             {
 46                 mm++;
 47                 nn=ans[i].x;
 48             }
 49             tt[ans[i].id]=mm;
 50         }
 51         for(i=1;i<=n;i++)
 52         {
 53             ans[i].x=tt[i];
 54         }
 55         int maxx=0;
 56         for(i=1; i<=n; i++)
 57         {
 58             cnt[ans[i].x]++;
 59             if(maxx<cnt[ans[i].x])
 60             {
 61                 maxx=cnt[ans[i].x];
 62             }
 63         }
 64         int l=1;
 65         int ask=1;
 66         int r=maxx;
 67         while(l<=r)
 68         {
 69             int mid=(l+r)/2;
 70             LL ak=check(mid);
 71             LL cnt1=(n)*(n-1)/2;
 72             if(ak>=m)
 73             {  ask=mid;
 74                l=mid+1;
 75             }
 76             else
 77             { r=mid-1;
 78 
 79             }
 80         }printf("%d
",ask);
 81     }
 82     return 0;
 83 }
 84 LL check(int mid)
 85 {
 86     int i,j,k;
 87     LL sum=0;
 88     if(mid==1)
 89         return n*(n-1)/2;
 90     else
 91     {
 92         memset(id,0,sizeof(id));
 93         memset(cnt,0,sizeof(cnt));
 94         memset(str,0,sizeof(str));
 95         cnt[ans[1].x]++;str[ans[1].x]=1;id[1]=0;
 96         for(i=2; i<=n; i++)
 97         {
 98             cnt[ans[i].x]++;
 99             if(cnt[ans[i].x]==1)
100             {
101                 str[ans[i].x]=i;
102                 id[i]=0;
103             }
104             else if(cnt[ans[i].x]==mid)
105             {
106                 id[i]=str[ans[i].x];
107             }
108             else if(cnt[ans[i].x]<mid)
109             {
110                 id[i]=0;
111             }
112             else  if(cnt[ans[i].x]>mid)
113             {
114                 while(cnt[ans[i].x]>mid)
115                 {
116                     str[ans[i].x]++;
117                     if(ans[str[ans[i].x]].x==ans[i].x)
118                     {
119                         cnt[ans[i].x]--;
120                         break;
121                     }
122                 }id[i]=str[ans[i].x];
123             }
124         }
125         int L=0;
126         LL sum=0;
127         for(i=1; i<=n; i++)
128         {
129             L=max(L,id[i]);
130             sum+=L;
131 
132         }printf("
");
133         return sum;
134     }
135 }
油!油!you@
原文地址:https://www.cnblogs.com/zzuli2sjy/p/5472343.html