HDU6058
题意:
对于这种纯暴力计算贡献的,我们考虑用每个数字的贡献来计算。
考虑每个数字作为第k大的数字,则左边有x个比它大的,右边就有k-x-1比它大的
记录比它大的位置,O(nk)可以实现,方便去除和记录用链表实现。[从小到大,周边的一定比自己大]
我们从最左边开始,往右搜保证每次数字都是第k大的。
最后加起来。
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
#define M 500050
int lft[M],rgt[M],pos[M];
int n,k;
ll sum;
void del(int x){
lft[rgt[x]]=lft[x];
rgt[lft[x]]=rgt[x];
}
void init(){
sum=0;
rgt[0]=1,lft[n+1]=n;
FOR(i,1,n){
int x;
scanf("%d",&x);
pos[x]=i;
lft[i]=i-1;
rgt[i]=i+1;
}
FOR(i,1,n){
int l=pos[i],r=pos[i],lt=0,rt=0;
while(lt<k&&l!=0)l=lft[l],lt++;
while(lt+rt<k&&r!=n+1)r=rgt[r],rt++;
while(r!=n+1&&rt<k&&l!=pos[i]){
sum+=1LL*(rgt[l]-l)*(rgt[r]-r)*i;
l=rgt[l],r=rgt[r],rt++;
}
del(pos[i]);
}
cout<<sum<<endl;
}
int main(){
int T;
cin>>T;
while(T--){
cin>>n>>k;
memset(lft,0,sizeof(lft));
memset(rgt,0,sizeof(rgt));
init();
}
}
CF
不难。只是要用链表简单维护一些删除操作。
这里介绍了数组链表在解决相邻元素问题的一大秒用。【求环内不相邻元素最大和】