zoukankan      html  css  js  c++  java
  • [CQOI]中位数 && 中位数(qbxt) && 众数(qbxt)

    给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。

    输入输出格式

    输入格式:

    第一行为两个正整数n和b,第二行为1~n的排列。

    【数据规模】

    对于30%的数据中,满足n≤100;

    对于60%的数据中,满足n≤1000;

    对于100%的数据中,满足n≤100000,1≤b≤n。

    输出格式:

    输出一个整数,即中位数为b的连续子序列个数。

    from 黄学长

    找到b在数列中的位置设为point,比b大的赋值为-1,比b小的赋值为1;

    然后求出sum[i,point]的值出现了几次记为lfre[sum[i,point]]++; ans += lfre[sum[i,point]]*rfre[-sum[i,point]];

    由于c++数组不能是负数,所以稍微处理一下

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxn=1e6+7;
     5 int n,b,tmp,ans;
     6 int a[maxn],sum[maxn],lft[maxn],rgt[maxn],t[maxn];
     7 int main(){
     8   cin>>n>>b;
     9   for(int i=1;i<=n;i++) cin>>a[i];
    10   for(int i=1;i<=n;i++){
    11     if(a[i]>b) t[i]=1;
    12     if(a[i]==b){t[i]=0;tmp=i;}
    13     if(a[i]<b) t[i]=-1; 
    14   }
    15   lft[n]=1;rgt[n]=1;
    16   for(int i=tmp-1;i>=1;i--){
    17     sum[i]=sum[i+1]+t[i];lft[sum[i]+n]++;
    18   }
    19   for(int i=tmp+1;i<=n;i++){
    20     sum[i]=sum[i-1]+t[i];rgt[sum[i]+n]++;
    21   }
    22   for(int i=0;i<2*n;i++){
    23     ans+=lft[i]*rgt[2*n-i];
    24   }
    25   cout<<ans<<endl;
    26   return 0;
    27 } 

    第k大一般用二分

    二分一个答案,将序列中大于它的数附为1,小于它的赋为-1,利用树状数组求顺序对,即中位数大于当前答案的区间的个数

    如果这个值大了,说明当前二分的答案小了,就要r=mid+1当然这里指的是在数列中的下标

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <queue>
     4 #include <cstring>
     5 #include <algorithm>
     6 #define N 200005
     7 #define ll long long
     8 using namespace std;
     9 int a[100010];
    10 int b[100010];
    11 int c[2][400010];
    12 int n;
    13 ll k;
    14 void add(int x,int y,int f){
    15     for(;x<=400000;x+=(x&(-x))){
    16         c[f][x]+=y;
    17     }
    18 }
    19 int query(int x,int f){
    20     int ret=0;
    21     for(;x>0;x-=(x&(-x))){
    22         ret+=c[f][x];
    23     }
    24     return ret;
    25 }
    26 bool check(int mid){
    27     ll ret=0;
    28     int tmp=0;
    29     memset(c,0,sizeof(c));
    30     add(N,1,0);
    31     for(int i=1;i<=n;i++){
    32         if(a[i]>=mid) tmp++;
    33         if(i&1){
    34             ret+=query(tmp*2-i+N,0);
    35             add(tmp*2-i+N,1,1);
    36         }
    37         else{
    38             ret+=query(tmp*2-i+N,1);
    39             add(tmp*2-i+N,1,0);
    40         }
    41     }
    42     return ret>=k;
    43 }
    44 int main(){
    45     freopen("kth.in","r",stdin);
    46     freopen("kth.out","w",stdout);
    47     scanf("%d%lld",&n,&k);
    48     for(int i=1;i<=n;i++){
    49         scanf("%d",&a[i]);
    50         b[i]=a[i];
    51     }
    52     sort(b+1,b+n+1);
    53     int tmp=unique(b+1,b+n+1)-b-1;
    54     for(int i=1;i<=n;i++){
    55         a[i]=lower_bound(b+1,b+tmp+1,a[i])-b;
    56     }
    57     int l=1;
    58     int r=tmp;
    59     while(l+1<r){
    60         int mid=l+r>>1;
    61         if(check(mid)) l=mid;
    62         else r=mid-1;
    63     }
    64     if(check(r)) cout<<b[r];
    65     else cout<<b[l];
    66     return 0;
    67 }
    68 /*--------------------- 
    69 作者:zhn_666 
    70 来源:CSDN 
    71 原文:https://blog.csdn.net/zhn_666/article/details/78236482 
    72 版权声明:本文为博主原创文章,转载请附上博文链接!*/

    维护两个指针l,r

    如果l~r这个区间的众数大于当前二分的值,那么[(1~l),r]都满足众数大于当前二分的值,

    所以当一个区间满足时(从l到r,出现的数a[i],则s[a[i]]++,最后找最大的s[i])

    l这个指针可以直接跳到r+1

  • 相关阅读:
    unigui在阿里云服务器上部署
    nativeexcel将excel导入数据集
    nativeexcel数据集导出excel
    超市收银系统
    cxgrid回车移到下一个单元格
    cxGrid单元格获得输入焦点
    TDiocpCoderTcpServer返回数据记录有条数限制的问题
    Ubuntu -- 配置Nginx和https及frp
    REMOTE HOST IDENTIFICATION HAS CHANGED 问题解决
    iOS -- iOS11新特性,如何适配iOS11
  • 原文地址:https://www.cnblogs.com/lcan/p/9695503.html
Copyright © 2011-2022 走看看