TIOJ1208 第K大连续和

第k大的题一般都有点麻烦

pbds库的tree,需要研究一下
https://codeforces.com/blog/entry/11080
find_by_order() and order_of_key(). The first returns an iterator to the k-th largest element (counting from zero), the second — the number of items in a set that are strictly smaller than our item
用pair<int,int>相当于 multiset
比较的应该是first,(还要再验证一下)

二分答案,然后每次判断中,遍历前缀和Bi,然后查找有多少个j<i ,满足 Bi-Bj>X,也就是有多少个子序列的和是大于X的,即使求有多少个Bj小于【Bi-X】

 

#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;

//插入查找都是logn,n次插入,nlogn;最后乘以logmaxans(解的范围)
typedef tree<pair<int,int>,null_type,less<pair<int,int>>,rb_tree_tag,tree_order_statistics_node_update> set_t;
const int SIZE = 1e6+10;
int a[SIZE],s[SIZE];
int main(){
    int  N,K;
    while(scanf("%d%d",&N,&K)&&N){
        for(int i=1;i<=N;i++){
            scanf("%d",&a[i]);
            s[i]=s[i-1]+a[i];
        }
        int ll=-10000*N,rr=10000*N;  //cnt 比guessans大或等的区间和个数(因为加了个1)
        while(ll<rr){
            int guessed_answer=(ll+rr+1)/2;
            set_t S;
            int cnt=0;
            for(int i=0;cnt<=K&&i<=N;i++){
                cnt+=S.order_of_key(make_pair(s[i]-guessed_answer+1,0));//返回严格小于给定值的个数
                S.insert(make_pair(s[i],i));
            }
            //printf("%d:%d\n",guessed_answer,cnt);
            if(cnt<K)rr=guessed_answer-1;
            else ll=guessed_answer;
        }
        printf("%d\n",ll);
    }
    return 0;
}

 

posted @ 2018-10-08 21:29  Erio  阅读(401)  评论(0编辑  收藏  举报