Codeforces 1005E1&2 Median on Segments (General Case & Permutations Edition)
Posted zhenghanghu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1005E1&2 Median on Segments (General Case & Permutations Edition)相关的知识,希望对你有一定的参考价值。
E1
想到的O(n)做法,因为m只会出现一次,所以subarray里必须包括m。可以想像合法的subarray是m左边一个连续区间+m+m右边一个连续区间组成。然后把左区间预处理,枚举右区间就行了。(根据性质:一个subarray的median是m,那说明有0个数净比m大,或有1个数净比m大)【净大指的是2个比m小,1个比m大,算-1个比m净大】
1 #include<iostream> 2 #include<map> 3 using namespace std; 4 5 long long a[200005],index,ans; 6 map<int,int> mp; 7 8 int main(){ 9 int n,m; cin>>n>>m; 10 for(int i=1;i<=n;i++){ 11 scanf("%lld",a+i); 12 if(a[i]==m) index=i; 13 } 14 15 int count=0; 16 mp[0]=1; 17 for(int i=index-1;i>=1;i--){ 18 if(a[i]>m) { count++; mp[count]++; } 19 else { count--; mp[count]++; } 20 } 21 22 count=0; 23 for(int i=index;i<=n;i++){ 24 if(a[i]>m) count++; 25 else if(a[i]<m) count--; 26 //cout<<count<<" "<<mp[-count]<<" "<<mp[-count+1]<<endl; 27 ans+=mp[-count]+mp[-count+1]; 28 } 29 30 cout<<ans; 31 32 return 0; 33 }
E2
这个做法与上一个完全不同,nlogn做法。
greatCount(m)返回有多少个subarray使得其median大于等于m,这样答案就是greatCount(m)-greatCount(m+1)
一个subarray的median要想大于等于m,那得有至少一个数净大于等于m。
维护一个sum[i]数组,代表1-i中有多少个数净大于等于m【就是大于等于m的数量减去小于m的数量】,那所有median大于m的区间都是 i>j, sum[i]-sum[j]>0 => sum[i]>sum[j]的问题。可以按值插入树状数组维护。
注意一下sum[i]里面可能是负数,所以在add的时候可以加上个大常数这样就变成正的了。
1 #include<iostream> 2 #include<map> 3 #include<algorithm> 4 #include<vector> 5 #include<cstring> 6 #define lowbit(x) x&(-x) 7 using namespace std; 8 9 int a[200005],s[200005],n; 10 int c[400005]; 11 12 void add(int index,int dx){ 13 for(;index<=n+200000;index+=lowbit(index)) c[index]+=dx; 14 } 15 16 int getSum(int n1){ 17 int ans=0; 18 for(;n1>0;n1-=lowbit(n1)) ans+=c[n1]; 19 return ans; 20 } 21 22 long long greatCount(int m){//有多少个segment使得它的median大于等于m 23 //枚举segment的结尾 24 memset(c,0,sizeof(c)); 25 long long result=0,sum=0; 26 //要想median大于m,sum[i]>sum[j] 27 //i>j, sum[i]>sum[j] 28 add(200000,1);//0-i 29 for(int i=1;i<=n;i++){ 30 if(a[i]>=m) sum+=1; 31 else sum-=1; 32 33 if(i!=n) add(sum+200000,1); 34 result+=getSum(sum-1+200000); 35 } 36 return result; 37 } 38 39 40 int main(){ 41 int median; cin>>n>>median; 42 for(int i=1;i<=n;i++) scanf("%d",a+i); 43 44 cout<<greatCount(median)-greatCount(median+1); 45 46 return 0; 47 }
以上是关于Codeforces 1005E1&2 Median on Segments (General Case & Permutations Edition)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #496 (Div. 3)未完结
Codeforces Round #344 (Div. 2)
CodeCraft-19 and Codeforces Round #537 (Div. 2)
CF1005E1 Median on Segments (Permutations Edition) 思维
Codeforces Round #601 (Div. 2) E1 Send Boxes to Alice (Easy Version)