hdu6058 Kanade's sum

来源:互联网 发布:纽约卡车 知乎 编辑:程序博客网 时间:2024/06/08 19:45


题解:找出x左右两边大于x的k个数,左边记为cntl右边记为cntr,当cntl+cntr==k时,开始统计有多少个区间以x为第k大值。

重点是从小到大找x,x的情况全部考虑完后,把x从链表里删掉。

复杂度为O(n*k)

#include<iostream>#include<stdio.h>using namespace std;typedef long long ll;const int maxn=1e6;int t,n,k,id[maxn];struct node{    int nxt,pre,id;}buf[maxn];ll ans;int main(){    scanf("%d",&t);    while(t--){        ans=0;        scanf("%d%d",&n,&k);        for(int x,i=1;i<=n;i++){            scanf("%d",&x);            id[x]=i;            buf[i]=node{i+1,i-1,i};        }        buf[n+1].id=n+1;        for(int i=1;i<=n;i++){            int l=id[i],r=id[i];            int cntl=1,cntr=0;            while(cntl<k){                if(buf[l].pre==0) break;                l=buf[l].pre;                cntl++;            }            while(cntl){                while(cntl+cntr<k){                    if(buf[r].nxt==n+1) break;                    r=buf[r].nxt;                    cntr++;                }                while(cntl+cntr>k){                    cntr--;                    r=buf[r].pre;                }                if(cntl+cntr==k){                    int L=buf[l].id-buf[buf[l].pre].id;                    int R=buf[buf[r].nxt].id-buf[r].id;                    ans+=(ll)L*R*i;                }                l=buf[l].nxt,cntl--;            }            buf[buf[id[i]].pre].nxt=buf[id[i]].nxt;            buf[buf[id[i]].nxt].pre=buf[id[i]].pre;        }        printf("%lld\n",ans);    }}


原创粉丝点击