考虑从小到大枚举x,每次维护一个链表,链表里只有>=x的数,那么往左往右找只要暴力跳k次,删除也是O(1)的
hdu 6058 Kanade’s sum
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int a[N];
int pos[N];
int pre[N];
int np[N];
int l[85];
int r[85];
void erases(int p){
pre[np[p]]=pre[p];
np[pre[p]]=np[p];
}
int main(){
int t;scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
for(int i=1;i<=n;i++){
pre[i]=i-1;
np[i]=i+1;
}
ll ans=0;
for(int num=1;num<=n;num++){
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
int p=pos[num];
int cnt1=0,cnt2=0;
for(int s=p;cnt1<=k&&s<=n;){
r[cnt1++]=s;
s=np[s];
}
r[cnt1]=n+1;
for(int s=p;cnt2<=k&&s>=1;){
l[cnt2++]=s;
s=pre[s];
}
l[cnt2]=0;
/* printf("\nr--");
for(int i=0;i<=cnt1;i++){
printf("%d ",r[i]);
}
printf("\nl--");
for(int i=0;i<=cnt2;i++){
printf("%d ",l[i]);
}*/
erases(p);
for(int j=0;j<k;j++){
if(j<=cnt2&&k-j<=cnt1)
ans+=(1ll*num*(l[j]-l[j+1])*(r[k-j]-r[k-j-1]));
//printf("ans--%I64d\n",ans);
}
}
printf("%I64d\n",ans);
}
}