• 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的时候可以加上个大常数这样就变成正的了。

    ===2018.9.4===不愧ACM里都是思维题,这题建完模以后就容易了

    找到一个区间里median正好是m的比较难,但一个区间里median大于等于m的可以nlogn处理出来

     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 }
  • 相关阅读:
    c++虚函数
    Boost Graph Library
    二分查找 http://ac.jobdu.com/problem.php?pid=1545
    二叉树应用
    注解篇二
    springboot+fastdfs+docker
    注解篇一
    vue启动加修改例子
    SSM框架中的中文乱码问题
    mybatis4
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9313271.html
Copyright © 2020-2023  润新知