别样的积木大赛(?)| 题解:CF1884E Hard Design
Petit_Souris · · 题解
先不考虑环,就做一个序列的情况。改变一下
第一问是容易的,就是经典的积木大赛,结论是
第二问我们考虑上面那个式子是怎么来的。如果你依稀记得积木大赛的做法的话,我们实际上是在维护目前覆盖到
最后考虑一下环怎么做。第一问还是容易的,第二问我们需要观察到一个很重要的事情:因为所有数都要改到最大值,所以最大值所在位置的
注意取模。
#include<bits/stdc++.h>
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define pii pair<ll,ll>
#define rep(i,a,b) for(ll i=(a);i<=(b);++i)
#define per(i,a,b) for(ll i=(a);i>=(b);--i)
using namespace std;
bool Mbe;
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void write(ll x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
const ll N=1e6+9,Mod=1e9+7;
ll T,n,a[N],top,L[N],R[N];
pii stk[N];
void solve(){
n=read();
rep(i,1,n)a[i]=read();
ll mx=*max_element(a+1,a+n+1);
rep(i,1,n)a[i]=mx-a[i];
top=0;
ll P=0;
rep(i,1,n){
if(!a[i])P=i;
}
rep(i,0,n+1)L[i]=R[i]=0;
ll lst=P,sum=0,cnt=0;
rep(i,1,n){
ll now=(lst==n?1:lst+1);
if(a[now]>a[lst]){
ll d=a[now]-a[lst];
stk[++top]={d,i},cnt+=d;
}
else {
ll d=a[lst]-a[now];
while(d){
if(stk[top].first<=d){
d-=stk[top].first,cnt-=stk[top].first,sum-=stk[top].first*(i-stk[top].second);
stk[top]={0,0},top--;
}
else cnt-=d,stk[top].first-=d,sum-=d*(i-stk[top].second),d=0;
}
}
R[i]=(R[i-1]+2*sum+cnt)%Mod,sum+=cnt,lst=now;
}
lst=P,sum=0,cnt=0;
rep(i,1,n){
ll now=(lst==1?n:lst-1);
if(a[now]>a[lst]){
ll d=a[now]-a[lst];
stk[++top]={d,i},cnt+=d;
}
else {
ll d=a[lst]-a[now];
while(d){
if(stk[top].first<=d){
d-=stk[top].first,cnt-=stk[top].first,sum-=stk[top].first*(i-stk[top].second);
stk[top]={0,0},top--;
}
else cnt-=d,stk[top].first-=d,sum-=d*(i-stk[top].second),d=0;
}
}
L[i]=(L[i-1]+2*sum+cnt)%Mod,sum+=cnt,lst=now;
}
ll C=0;
rep(i,1,n){
ll lst=(i==1?n:i-1);
C+=max(0ll,a[i]-a[lst]);
}
rep(i,1,n){
ll lst=(i==1?n:i-1);
ll ncnt=C-max(0ll,a[i]-a[lst])+a[i];
write(ncnt),putchar(' ');
if(P>=i)write((L[P-i]+R[n-(P-i)-1])%Mod);
else write((R[i-P-1]+L[n-(i-P-1)-1])%Mod);
putchar('\n');
}
}
bool Med;
int main(){
cerr<<fabs(&Med-&Mbe)/1048576.0<<"MB\n";
T=read();
while(T--)solve();
cerr<<"\n"<<clock()*1.0/CLOCKS_PER_SEC*1000<<"ms\n";
return 0;
}