(problem)
在皮卡多捡到了一件三级甲的老王非常兴奋,想马上测试一下三级甲的性能,于是老王走到了加油站旁边的空地上跳俄舞,不一会儿身上就被打了一排子弹,老王躲起来后脱下三级甲,发现这一排弹孔深度不一,聪明的老王想到了一个量化计算性能的方法,给定一个(k≤n),计算出所有长度为 (k) 的区间的弹孔深度的最小值的和,当然 (k) 值不同,得到的性能值也不同,所以老王会取不同的 (k) 进行计算,为了帮助老王吃鸡,这个问题就交给你来解决。
Solution
考场上想到了代价转贡献,但是没有考虑全面,倍增处理最小值时炸了
正解其实是一个二维差分,就是贡献大概是前缀,后缀加上一段常数,可以用差分来维护
因为懒得写单调队列就写了暴力,结果一发90pts?! 再判断一个特殊性质就A了
(Code)
#include<bits/stdc++.h>
using namespace std;
#define fr(i,a,b) for(int i=a;i<=b;++i)
#define rf(i,a,b) for(int i=a;i>=b;--i)
template<typename T>
inline void read(T &x){
char c=getchar();x=0;bool f=0;
while(!isdigit(c))f|=(c=='-'),c=getchar();
while(isdigit(c))x=x*10+(c^48),c=getchar();
x=f?-x:x;
}
typedef long long ll;
const int N=1e6+5;
ll ans[N];
ll ans2[N],Ans1[N],Ans2[N],ans1[N],a[N];
int n,m,k;
int main(){
// freopen("vest.in","r",stdin);
// freopen("vest.out","w",stdout);
read(n),read(m);
int f=0;
fr(i,1,n)read(a[i]),f|=(a[i]!=i);
if(!f){
while(m--){
read(k);
printf("%lld
",1ll*(n-k+1)*(n-k+2)/2);
}
return 0;
}
fr(i,1,n){
int l=i,r=i+1;
while(a[l]>=a[i]&&l)--l;++l;
while(a[r]>a[i]&&r<=n)++r;--r;
int nw=min(i-l+1,r-i+1),nw1=max(i-l+1,r-i+1),nw2=r-l+1;
if(nw-1>=1)ans[1]+=a[i],ans[nw]-=a[i],Ans1[nw]-=(nw-1)*a[i];
if(nw1+1<=nw2)ans2[nw2]+=a[i],ans2[nw1]-=a[i],Ans2[nw1]-=(nw-1)*a[i];
ans1[nw]+=nw*a[i],ans1[nw1+1]-=nw*a[i];
}
fr(i,1,n){
ans[i]+=ans[i-1];
Ans1[i]+=ans[i]+Ans1[i-1];//left
ans1[i]+=ans1[i-1];//middle
}
rf(i,n,1){//right
ans2[i]+=ans2[i+1];
Ans2[i]+=Ans2[i+1]+ans2[i];
}
while(m--){
read(k);
printf("%lld
",Ans1[k]+Ans2[k]+ans1[k]);
}
}