WUST OJ 2057: 第K大子串和

来源:互联网 发布:赵氏孤儿知乎 编辑:程序博客网 时间:2024/05/18 15:54

2057: 第K大子串和

                                                                          Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lld

Description

给出一个长度为的序列,有M次询问,每次询问第K大的子串(连续的子序列)之和

Input

多组测试数据

每组数据一行为N,表示序列的长度 (N <= 10000

第二行有N个数A1 A2 … An用空格隔开,表示序列中的数( 0 <= Ai <= 10000)

接下来一行有一个数M,表示询问的次数(M<=100

接下来M行,每行一个正整数K( K<= N*(N-1)/2 )

Output

输出一个数表示第K大的子串和

Sample Input 

4

1 2 3 2

2

1

2


Sample Output

8

7

蛮好的一个题。

思路:二分枚举子串和,利用尺取判断其是不是第k大。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,a[10001];int lenka(int mid){    int sum=a[0],begin=0,end=0,k=0;    while(end<n)    {        if(sum>=mid)        {            k+=n-end;            sum-=a[begin];            begin++;            if(begin>end)            {                end=begin;                sum=a[begin];            }        }        else        {            end++;            sum+=a[end];        }    }    return k;}int main(){    int T,k,up,low,mid,QWQ;    while(scanf("%d",&n)!=EOF)    {        int ma=0,mi=10000;        for(int i=0;i<n;i++)scanf("%d",&a[i]),ma+=a[i],mi=min(mi,a[i]);        scanf("%d",&T);        while(T--)        {            scanf("%d",&k);            up=ma,low=mi;            mid=(up+low)/2;            while(up>=low)            {                mid=(up+low)/2;                QWQ=lenka(mid);                //printf("有%d个比%d大\n",QWQ,mid);                if(QWQ>=k)low=mid+1;                else up=mid-1;            }            printf("%d\n",up);        }    }    return 0;}