zoukankan      html  css  js  c++  java
  • MZOJ #81 最小得分和

    分析

    1.不能再暴力的暴力(40)

    最暴力的方法:将所有的差求出来然后排序,选出最小的k个

    复杂度:O (N2logN)

    2.比较不暴力的暴力(80)

    还记得蚯蚓吗,决策单调

    这道题其实也有隐藏的单调,甚至比蚯蚓还要明显的多

    先将n个数排序,当然,离i越近,差越小,这是相对i而言的

    不过蚯蚓哪里只要三个队列就好,这里,如果用那个方法,怕是要n个队列

    这道题还是用堆吧,看下面hty的题解中的80分做法

    机房里也有大佬这么做

    首先将每相邻两个元素差值入堆,每次选取当前堆中最小的数,找到它在原序列中的位置i,然后向左找到第一个没有取的数对(ip[i]),将堆顶元素变为s[i]-s[p[i]-1],s[i]为前缀和,然后decp[i]),做K次得到答案

    复杂度:O(KlogN)

    3.满分做法(100)

    我考场上并没有想到80分的做法,直接由最暴力的做法得到了思路,于是写了正解……

    然而我觉得80分的做法比正解要难想诶

     我们先看看暴力:

    最暴力的方法:将所有的差求出来然后排序,选出最小的k个

    对于每一个差,我们都可以找到一个减数,一个被减数

    为了简化问题,我们将n个数从小到大排序,以免不必要的枚举

    我们可以发现,对于每一个被减数,一定是离他近的减数与他相减所得的差小

    有了以上分析的单调性,我们再看,对于每一个差值,差值越大,那么小于等于它的差值就越多

    废话

    对,就是这个性质,给了我们二分的可能

    我们所求的就是前k个最小的差不是吗,这k个差有上限,也就是第k大的差值 

    不如就二分这个上限,我们可以在O(n)的时间内求出这个上限所含的差值的个数:

    求出了我们的上限,我们应该怎么算答案呢?

    且看上面的程序,在求个数的时候,我们明显还维护了被减数的减数下限(也就是每一个i所对应的j)

    a[i] 与a[j] ~ a[i-1]的差都小于等于第k大的差,都是要加到答案里的

    重新组合整理一下,就变成了这样:

    这个,完全可以用前缀和优化呀

    于是,最终版是这样的:

    Over

    不对,你以为就这样完了?

    太天真了

    WA快乐

    我们求出了第k大的值,可谁说小于等于第k大的差值就一定有k个呢

    Σ(っ°Д°;)っ

    看这组数据,

    4 5

    1 1 2 3

    我们求出的差值为

    0 1 1 1 2 2

    第5大的是2,但是2有两个,上述代码没有处理多余的2

    所以,代码的最后需要减去多余的2

    cnt是实际小于等于第k大的差值的个数,cur是第k大的差值的值

    真的Over了

    复杂度:O(NlogN+NlogaN

    4.题解 By hty(^v^)

    题解当然要最后放……

    代码

     1 /********************
     2 User:Mandy
     3 Language:c++
     4 Problem:
     5 ********************/
     6 #include<bits/stdc++.h>
     7 
     8 using namespace std;
     9 
    10 typedef long long ll;
    11 
    12 const int maxn = 1e6 + 5;
    13 
    14 ll n,k;
    15 ll a[maxn];
    16 ll sum[maxn];
    17 char *TT,*mo,but[(1 << 15) + 2];
    18 #define getchar() ((TT == mo && (mo = ((TT = but) + fread(but,1,1 << 15,stdin)),TT == mo)) ? -1 : *TT++) 
    19 template<class T>inline void read(T &x){
    20     x = 0;bool flag = 0;char ch = getchar();
    21     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
    22     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
    23     if(flag) x = -x;
    24 }
    25 
    26 template<class T>void putch(const T x){
    27     if(x > 9) putch(x / 10);
    28     putchar(x % 10 | 48);
    29 }
    30 
    31 template<class T>void put(const T x){
    32     if(x < 0) putchar('-'),putch(-x);
    33     else putch(x);
    34 }
    35 
    36 void file(){
    37     freopen("mark.in","r",stdin);
    38     freopen("mark.out","w",stdout);
    39 }
    40 
    41 void readdata(){
    42     read(n);read(k);
    43     for(int i = 1;i <= n; ++ i) read(a[i]);
    44     sort(a + 1,a + 1 + n);
    45 }
    46 
    47 bool check(ll x){
    48     ll j = 1,cnt = 0;
    49     for(ll i = 2;i <= n; ++ i){//被减数 
    50         
    51         while(a[i] - a[j] > x)//减数 
    52             j++;
    53         cnt += i - j;
    54         if(cnt >= k) return 1;
    55     }
    56     return 0;
    57 }
    58 
    59 void work(){
    60     long long l = 0,r = a[n] - a[1],cur;
    61     while(l <= r){//二分第k大的差 
    62         ll mid = (l + r) >> 1;
    63         if(check(mid)) cur = mid,r = mid - 1;
    64         else l = mid + 1;
    65     } 
    66     ll j = 1;
    67     for(int i = 1;i <= n; ++ i) sum[i] = sum[i - 1] + a[i];
    68     ll cnt = 0,ans = 0;
    69     for(ll i = 2; i <= n ; ++ i){
    70         while(a[i] - a[j] > cur) j++;
    71         ans = ans - (sum[i-1] - sum[j-1]) + a[i] * (i-j);
    72         cnt += (long long)i-j; 
    73     }
    74     if(cnt > k) ans -= cur * (cnt - k);
    75     put(ans);
    76 }
    77 
    78 int main(){
    79 //    file();
    80     readdata();
    81     work();
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    Codeforces Round #383 D
    [HNOI2010]弹飞绵羊
    多项式幂函数(加强版)
    「ZJOI2015」地震后的幻想乡
    [AHOI2013]作业
    MVC3+EF4.1学习系列(九)-----EF4.1其他的一些技巧的使用
    MVC3+EF4.1学习系列(八)-----利用Repository and Unit of Work重构项目
    MVC3+EF4.1学习系列(七)-----EF并发的处理
    MVC3+EF4.1学习系列(六)-----导航属性数据更新的处理
    MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11477804.html
Copyright © 2011-2022 走看看