CF1556E Equilibrium
题目大意
给定两个长度为 \(n\) 的序列 \(a,b\)。现在有 \(Q\) 组询问。对于每组询问可以做若干组操作,每次在 \(l,r\) 中选择偶数长度的子序列,子序列的第奇数个 \(a_{p_i}\)加 \(1\),偶数位置 \(b_{p_j}\) 减 \(1\)。求是否可以将 \(a,b\) 在 \(l,r\) 里调整对应相等,求最小次数。
\(n\leq 10^5\)。
思路
调整问题可以先做一下对应的差分。那么设 \(c_i=b_i-a_i\)。则每一次操作就是让奇数位置 \(-1\) 偶数位置 \(+1\)。那么首先有和不变所以和不为 \(0\) 就一定无解。
接下来比较牛。我们考虑将正数 \(x\) 看成 \(x\) 个左括号,负数 \(x\) 看成 \(|x|\) 个右括号。那么上述的操作就可以转化成选择一个形如 ()()()... 的子序列删去。那么我们不难观察到有解的一个前提还得是 \(c_{l\cdots r}\) 是一个合法的括号序列。
那么考虑最小操作次数。发现就是前缀最大左括号未匹配个数。
代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
ll c[MAXN],f[MAXN];
int n,Q;
ll st[2][MAXN][17];
ll query(int id,int l,int r){
int j=__lg(r-l+1);
if(id==0){
return min(st[0][l][j],st[0][r-(1<<j)+1][j]);
}
return max(st[1][l][j],st[1][r-(1<<j)+1][j]);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>Q;
rep(i,1,n){
cin>>c[i];
}
rep(i,1,n){
int x;
cin>>x;
c[i]=x-c[i];
f[i]=f[i-1]+c[i];
st[0][i][0]=st[1][i][0]=f[i];
}
rep(j,1,__lg(n)){
rep(i,1,n-(1<<j)+1){
st[0][i][j]=min(st[0][i][j-1],st[0][i+(1<<(j-1))][j-1]);
st[1][i][j]=max(st[1][i][j-1],st[1][i+(1<<(j-1))][j-1]);
}
}
rep(i,1,Q){
int l,r;
cin>>l>>r;
if(f[r]-f[l-1]!=0){
cout<<-1<<"\n";
continue;
}
if(query(0,l,r)<f[l-1]){
cout<<-1<<"\n";
continue;
}
cout<<query(1,l,r)-f[l-1]<<"\n";
}
return 0;
}

浙公网安备 33010602011771号