样例全过0分,玄关
查看原帖
样例全过0分,玄关
638119
封禁用户楼主2024/3/16 16:24

单调队列+差分做法

#include<bits/stdc++.h>
using namespace std;
long long n,p[500005],q[500005],a[500005],l[500005],r[500005];
void f(long long L,long long R,long long x,long long y){
	if(l>r) return ;
	p[L]+=x,p[R+1]-=x,p[R+1]-=y*(R-L),q[L+1]+=y,q[R+1]-=y;
}
int main(){
	/*
	
	*/
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i+n]=a[i+n+n]=a[i];
	}
	
	for(int i=1;i<=n;i++) r[i]=n*3+i,l[i]=0;
	stack<long long> que,sta;
	for(int i=1;i<=n*3;i++){
		while(que.size()&&a[que.top()]>=a[i]) que.pop();
		l[i]= que.size() ? que.top() : l[i],que.push(i);
	}//cout<<1;
	for(int i=n*3;i>0;i--){
		while(sta.size()&&a[sta.top()]>a[i]) sta.pop();
		r[i]= sta.size() ? sta.top() : r[i],sta.push(i);
	}//for(int i=1;i<=n*3;i++) cout<<l[i]<<r[i]<<' ';
	
	for(long long i=1;i<=n;i++){
		l[i]=max(l[i+n],i)-n;
		r[i]=min(r[i+n],i+2*n)-n;
		f(1ll,min(i-l[i],r[i]-i),a[i],a[i]);
		f(min(i-l[i],r[i]-i)+1,max(i-l[i],r[i]-i),(min(i-l[i],r[i]-i))*a[i],0);
		f(max(i-l[i],r[i]-i)+1,r[i]-l[i]-1,(min(i-l[i],r[i]-i))*a[i]-a[i],-a[i]);
	}
	for(int i=1;i<=n;i++){
		q[i]+=q[i-1],p[i]+=q[i];
	}
	for(int i=2;i<=n;i++){
		p[i]+=p[i-1];
		cout<<p[i]<<endl;
	}
	cout<<p[n];
	return 0;
}


2024/3/16 16:24
加载中...