[题解]CF1473D Program

思路

因为此题目中对于数的更新只能为 1,所以,如果我们找到了 [1,l1][r+1,n] 中能获得的两个极值即可。

我们为 S 赋予权值,用一个数组 a 储存:

  1. 如果 Si+,则其权值为 1
  2. 否则其权值为 1

那么,在第 i 次操作后,能产生的数是 j=1iaj

考虑用前缀和维护这个数,记作 s

因为它是一个静态的问题,所以用 ST 表维护一下前缀和的极值。

对于前一部分(即 [1,l1]),只需要求出 maxi[1,l1]{si}mini[1,l1]{si};对于后一部分,只需要求出 maxi[r+1,n]{si}sr+sl1mini[r+1,n]{si}sr+sl1 即可。(因为 [l,r] 区间被忽略了)

此外,需要注意的是,如果 0 未包含在两个极值之间,需要将答案额外加上 1

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 2e5 + 10,M = 25,inf = 0x3f3f3f3f;  
int T,n,q;  
int arr[N],lg[N + 10];  
string s;  
  
struct ST{  
    #define pot(x) (1 << x)  
  
    int dp1[N][M],dp2[N][M];//dp1 维护最小值,dp2 维护最大值   
  
    inline void init(){  
        for (re int j = 1;j <= lg[n];j++){  
            for (re int i = 1;i <= n - pot(j) + 1;i++){  
                dp1[i][j] = min(dp1[i][j - 1],dp1[i + pot(j - 1)][j - 1]);  
                dp2[i][j] = max(dp2[i][j - 1],dp2[i + pot(j - 1)][j - 1]);  
            }  
        }  
    }  
  
    inline int query_Min(int l,int r){  
        int x = lg[r - l + 1];  
        return min(dp1[l][x],dp1[r - pot(x) + 1][x]);  
    }  
  
    inline int query_Max(int l,int r){  
        int x = lg[r - l + 1];  
        return max(dp2[l][x],dp2[r - pot(x) + 1][x]);  
    }  
  
    #undef pot  
}st;  
  
inline void Log(){  
    lg[1] = 0;  
    for (re int i = 2;i <= N;i++) lg[i] = lg[i / 2] + 1;  
}  
  
inline int sum(int l,int r){  
    return arr[r] - arr[l - 1];  
}  
  
int main(){  
    ios::sync_with_stdio(0);  
    cin.tie(0);  
    cout.tie(0);  
    cin >> T;  
    Log();  
    while (T--){  
        cin >> n >> q >> s;  
        s = ' ' + s;  
        for (re int i = 1;i <= n;i++){//转化权值   
            if (s[i] == '+') arr[i] = arr[i - 1] + 1;  
            else arr[i] = arr[i - 1] - 1;  
        }  
        for (re int i = 1;i <= n;i++) st.dp1[i][0] = st.dp2[i][0] = arr[i];  
        st.init();  
        while (q--){  
            int l,r;  
            cin >> l >> r;  
            int l1 = 1,r1 = l - 1;  
            int l2 = r + 1,r2 = n;  
            int Min = inf,Max = -inf;  
            if (l1 <= r1){//避免出现 l = 1 的情况   
                Min = min(Min,st.query_Min(l1,r1));  
                Max = max(Max,st.query_Max(l1,r1));  
            }  
            if (l2 <= r2){//避免出现 r = n 的情况   
                Min = min(Min,st.query_Min(l2,r2) - sum(l,r));  
                Max = max(Max,st.query_Max(l2,r2) - sum(l,r));  
            }  
            if (Min == inf) Min = 0;//特判 l = 1 且 r = n 的情况   
            if (Max == -inf) Max = 0;  
            if (Min <= 0 && 0 <= Max) cout << (Max - Min + 1) << "\n";  
            else cout << (Max - Min + 2) << "\n";  
        }  
    }  
    return 0;  
}  

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18264795

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示