1. 程式人生 > >Codeforces 1005E1&2 Median on Segments (General Case & Permutations Edition)

Codeforces 1005E1&2 Median on Segments (General Case & Permutations Edition)

mes map cas tor ++ edit tco mem perm

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)