、

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;
}
posted @ 2026-09-24 14:42  tanghg  阅读(4)  评论(0)    收藏  举报