• Educational Codeforces Round 102 (Rated for Div. 2)D. Program


    D. Program

    题意

    给你一个(x)初始值为0,然后给你一系列(+-)操作,问你忽略掉([l, r])区间的操作后,经过一系列操作,操作过程中会出现多少个不同的数字。比如说:0,1,2算三种,0,1, 0算2种

    思路

    容易发现一个区间([x,y])其中出现的数的可能有(max([x,y])-min([x,y]))但是需要注意和0的关系问题,因为(x)的初始值为0。

    三种情况分情况讨论:

    [l,r]在最左部分也就是有效部分为[x,n],此时(max([x,n]) - min([x, n]))然后判断和0的关系

    [l,r]在最右部分也就是有效部分为[1,x],此时(max([1,x]) - min([1,x]))然后判断和0的关系

    如果[l,r在中间]那么我们将右面的部分减去[l,r]之间的影响值,也就是将左右两部分合并。

    因为中间对右面的影响是固定值:(a[r] - a[l - 1]),然后同上和0讨论。

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 2e5 + 10;
    const int lgn = 21;
    //#define int long long
    
    int qmax[N][21], qmin[N][21];
    int lg[N];
    void init() {
    	lg[1] = 0, lg[2] = 1;
    	for (int i = 3; i < N; ++i)lg[i] = lg[i >> 1] + 1;
    }
    
    void st(int n) {
    	for (int j = 1; j < lgn; ++j) {
    		for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
    			qmax[i][j] = max(qmax[i][j - 1], qmax[i+ (1 << (j - 1))][j - 1]);
    			qmin[i][j] = min(qmin[i][j - 1], qmin[i+ (1 << (j - 1))][j - 1]);
    		}
    	}
    }
    
    int lmax(int l, int r) {
    	int len = lg[r - l + 1];
    	return max(qmax[l][len], qmax[r - (1 << len) + 1][len]);
    }
    
    int lmin(int l, int r) {
    	int len = lg[r - l + 1];
    	return min(qmin[l][len], qmin[r - (1 << len) + 1][len]);
    }
    
    int psum[N];
    
    int cal(int l1, int r1 ,int l2, int r2) {
    	r1 = max({r1, r2, 0});
    	l1 = min({l1 , l2, 0});
    	return r1 - l1 + 1;
    }
    void solve() {
    	int n, m; cin >> n >> m;
    	string str; cin >> str;
    	for (int i = 0; i < str.size(); ++i) {
    		if (str[i] == '+') psum[i + 1] = psum[i] + 1;
    		else psum[i + 1] = psum[i] - 1;
    		qmax[i + 1][0] = qmin[i + 1][0] = psum[i + 1];
    	}
    	st(n);
    	while (m --) {
    		int l, r; cin >> l >> r;
    		int l1, r1, l2, r2;
    		if (l == 1) {
    			l1 = 0;
    			r1 = 0;
    		} else {
    			l1 = lmin(1, l - 1);
    			r1 = lmax(1, l - 1);
    		}
    		if (r == n) l2 = 0, r2 = 0;
    		else {
    			l2 = lmin(r + 1, n);
    			r2 = lmax(r + 1, n);
    			l2 -= psum[r] - psum[l - 1];
    			r2 -= psum[r] - psum[l - 1];
    		}
    		cout << cal(l1 ,r1 ,l2 ,r2) << endl;
    	}
    }
    
    
    signed main() {
    	init();
    	ios::sync_with_stdio(false);
    	cin.tie(0);
        int T = 1;
        cin >> T;
        while (T--) {
            solve();
        }
    
    }
    
  • 相关阅读:
    python os模块 常用命令
    将excel表格中的数据导入到SQL中
    临时数据表DataTable selected方法的使用
    ASP.NET数据库使用精典读取数据库中数据
    新兵开唱
    DropDownList控件的changed事件调用
    C# 读取Excel表格中的数据
    C# 强制类型转换示例
    用ADO.NET的ExecuteScalar方法返回单一值
    CentOS 6.3 桥接上网
  • 原文地址:https://www.cnblogs.com/waryan/p/14287602.html
Copyright © 2020-2023  润新知