题解:P12969 [CCO 2025] Restaurant Recommendation Rescue
masterhuang · · 题解
现在两篇题解都不知道在说什么,而且做复杂了。真难蚌。
把输入的数
给定一个整数序列 0 0 即可。
定义
将
若
注意到循环位移前缀和有结论,设序列
循环位移
循环位移
循环位移
循环位移
对于这题,
右移
取
若
x\neq p ,取i=p 矛盾。若
x=p ,无论i 如何取值都能保证\ge 0 。
交换两个数
线段树维护区间加,最靠左侧的最小值。复杂度
::::info[
#include<bits/stdc++.h>
#define LL long long
#define P pair<LL,LL>
#define fi first
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
const int N=5e5+5;
int n,m,a[N];LL s[N],lt[N<<2];P A[N<<2];
#define ls w<<1
#define rs ls|1
#define lw l,m,ls
#define rw m+1,r,rs
inline void upd(int w,LL x){A[w].fi+=x,lt[w]+=x;}
inline void pd(int w){LL &t=lt[w];if(t) upd(ls,t),upd(rs,t),t=0;}
void bd(int l=1,int r=n,int w=1)
{
if(l==r) return A[w]={s[l],l},void();
int m=(l+r)>>1;bd(lw);bd(rw);A[w]=min(A[ls],A[rs]);
}
void UPD(int L,int R,LL x,int l=1,int r=n,int w=1)
{
if(L<=l&&r<=R) return upd(w,x);
int m=(l+r)>>1;pd(w);
if(L<=m) UPD(L,R,x,lw);
if(m<R) UPD(L,R,x,rw);A[w]=min(A[ls],A[rs]);
}
inline void get(){int p=A[1].second;cout<<"1 "<<(p==n?0:p)<<"\n";}
int main()
{
cin.tie(0)->sync_with_stdio(0);cout.tie(0);cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],s[i]=s[i-1]+(--a[i]);
if(s[n]!=-1){
for(m++;m--;) puts("0 0");return 0;
}bd();get();
for(int x,y;m--;)
{
cin>>x>>y;if(++x>++y) swap(x,y);
if(x<y) UPD(x,y-1,a[y]-a[x]);
swap(a[x],a[y]),get();
}
return 0;
}
::::