zoukankan      html  css  js  c++  java
  • CodeForces

    CodeForces - 1473D Program 前缀和,最大子段和

    题意

    给定一段“+-”序列,(+)表示(+1),否则表示(-1)

    现有(l ,r)表示无视([l,r])剩下的序列能够得到多少种不同的数字

    [1leq n,m leq 2 imes 10^5\ 1 leq l,r leq n ]

    分析

    显然答案 = 从左到右 序列过程中的最大值减去最小值

    去除([l,r])后将原序列分成两部分,左边的最值显然可以用前缀和维护。

    现在需要想一个办法来维护后缀的前缀,显然不能直接维护后缀的,于是用类似最大子段和的方法来维护后缀

    代码

    char s[maxn];
    int pre[maxn];
    int pre_mx[maxn],pre_mi[maxn],suf_mx[maxn],suf_mi[maxn];
    
    void solve(){
    	int n = rd();
    	int m = rd();
    	scanf("%s",s);
    	for(int i = 1;i <= n;i++){
    		pre[i] = pre[i - 1] + (s[i - 1] == '+' ? 1 : -1);
    		pre_mx[i] = max(pre[i],pre_mx[i - 1]);
    		pre_mi[i] = min(pre[i],pre_mi[i - 1]);
    	}
    	suf_mx[n + 1] = suf_mi[n + 1] = 0;
    	for(int i = n;i >= 1;i--){
    		suf_mx[i] = max(0,suf_mx[i + 1] + (s[i - 1] == '+' ? 1 : -1));
    		suf_mi[i] = min(0,suf_mi[i + 1] + (s[i - 1] == '+' ? 1 : -1));
    	}
    	while(m--){
    		int l = rd();
    		int r = rd();
    		l--;
    		int mx,mi;
    		mx = mi = 0;
    		mx = max(mx,pre_mx[l]);
    		mi = min(mi,pre_mi[l]);
    		int tmp = pre[l];
    		mx = max(mx,suf_mx[r + 1] + tmp);
    		mi = min(mi,suf_mi[r + 1] + tmp);
    		cout << mx - mi + 1 << '
    ';
    	} 
    }
    
    int main(){
    	int T = rd();
    	while(T--)
    		solve();
    }
    
  • 相关阅读:
    取字符串前缀
    分解质因数
    git 常用命令
    微信 iphone端 audio 播放问题
    git入门:创建合并分支 解决冲突 分支管理策略
    git入门:远程仓库 github篇
    git入门:撤销修改 删除文件
    git入门: 工作区暂存区 以及 管理修改
    函数柯里化实现
    转载:深度工作:充分使用每一份脑力
  • 原文地址:https://www.cnblogs.com/hznumqf/p/14376411.html
Copyright © 2011-2022 走看看