专栏文章
P13509 [OOI 2024] Almost Certainly 题解
P13509题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minp4vm3
- 此快照首次捕获于
- 2025/12/02 06:03 3 个月前
- 此快照最后确认于
- 2025/12/02 06:03 3 个月前
考虑维护一棵值域线段树 。对于每一个 ,将 上 的位置的值加 ,于是 可以变成 当且仅当 上每一个位置都大于等于 ,此时需要的操作次数为 。
由于「几乎等价」等价于「各删除一个数后完全相等」,设我们删除的是 和 ,那么我们希望删除的 尽可能大,这样才能使操作次数尽可能小。但是我们要保证删除后 上每一个位置都大于等于 ,所以需要满足 上 的每一个位置都大于等于 ,于是在 上计算最长的大于等于 的区间的长度即可。
可以离散化一下,时间复杂度 。
C#define int long long
const int N=2e5+5,inf=2e9;
int n,m,ans,a[N],b[N],t[N<<1],val[N<<3],lef[N<<3],rig[N<<3],mid[N<<3],sum[N<<3];
bool tag[N<<3];
void upd(int g){
sum[g]=sum[g<<1]+sum[g<<1|1];
lef[g]=max(lef[g<<1],val[g<<1]+lef[g<<1|1]);
lef[g]=max(lef[g],val[g<<1]);
rig[g]=max(rig[g<<1|1],rig[g<<1]+val[g<<1|1]);
rig[g]=max(rig[g],val[g<<1|1]);
mid[g]=max(mid[g<<1],mid[g<<1|1]);
mid[g]=max(mid[g],rig[g<<1]+lef[g<<1|1]);
mid[g]=max(mid[g],max(lef[g<<1|1],rig[g<<1]));
val[g]=val[g<<1]+val[g<<1|1];
}
void down(int g){
if(tag[g]){
tag[g<<1]=tag[g<<1|1]=1;
tag[g]=0;
mid[g<<1]=lef[g<<1]=rig[g<<1]=val[g<<1]=sum[g<<1];
mid[g<<1|1]=lef[g<<1|1]=rig[g<<1|1]=val[g<<1|1]=sum[g<<1|1];
}
}
void build(int g,int l,int r){
tag[g]=0;
if(l==r){
sum[g]=t[r]-t[r-1];
mid[g]=0;
lef[g]=rig[g]=val[g]=-inf;
return;
}
int m=(l+r)>>1;
build(g<<1,l,m);
build(g<<1|1,m+1,r);
upd(g);
}
void modify(int g,int l,int r,int x,int y){
if(x<=l&&r<=y) return mid[g]=lef[g]=rig[g]=val[g]=sum[g],tag[g]=1,void();
if(r<x||y<l) return;
int m=(l+r)>>1;
down(g);
modify(g<<1,l,m,x,y);
modify(g<<1|1,m+1,r,x,y);
upd(g);
}
void solve(){
cin>>n,ans=0;
for(int i=1;i<=n;i++) cin>>a[i],t[i]=a[i];
for(int i=1;i<=n;i++) cin>>b[i],t[i+n]=b[i];
sort(t+1,t+n+n+1);
m=unique(t+1,t+n+n+1)-t-1;
build(1,1,m);
for(int i=1;i<=n;i++){
ans+=a[i]-b[i];
int x=lb(t+1,t+m+1,b[i])-t,y=lb(t+1,t+m+1,a[i])-t;
modify(1,1,m,x+1,y);
cout<<ans-max(mid[1],max(lef[1],max(rig[1],val[1])))<<' ';
}
cout<<endl;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...