zoukankan      html  css  js  c++  java
  • AtCoder F

    原题链接:AtCoder F - Parenthesis Checking

    一个全由('(')(')')构成的字符串,由以下两个操作:

    • 1 l r交换字符串第(l)个和第(r)个字符。
    • 2 l r询问(S[l-r])是否是一个合法序列。

    很明显是一个线段树操作,这题蓝桥杯貌似有类似的,但是那道题貌似要用平衡树,也是操作之后判断括号序列是否合法,现在终于找到答案了,方法。

    我们让('(')(1),让(')')(-1),那么这样括号序列就成了只有(1)(-1)的一个序列,然后我们用线段树维护一个区间和,那么一个合法括号序列的条件就是这段区间和等于(0),然后这个区间的前缀和得大于(0)

    区间和好维护,但是区间前缀和怎么维护,那我们就维护一个前缀最小值就(ok)了,对于(pushup),也就是(min(左子树的最小值,左子树的和+右子树最小值)),很巧妙,塞给队友队友直接秒了,然后我想了一天多。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2E5 + 10;
    int W[N];
    
    struct SegmentTree {
    	int l, r;
    	int sum, pre_min;
    } tr[N * 4];
    
    void push_up(int u) {
    	tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
    	tr[u].pre_min = min(tr[u << 1].pre_min, tr[u << 1].sum + tr[u << 1 | 1].pre_min);
    }
    
    void build(int u, int l, int r) {
    	if (l == r) {
    		tr[u] = { l, r, W[r], W[r] };
    	}
    	else {
    		int mid = l + r >> 1;
    		tr[u] = { l, r };
    		build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    		push_up(u);
    	}
    }
    
    void modify(int u, int x, int v) {
    	if (tr[u].l == tr[u].r) {
    		tr[u].sum = tr[u].pre_min = v;
    	}
    	else {
    		int mid = tr[u].l + tr[u].r >> 1;
    		if (x <= mid) modify(u << 1, x, v);
    		else modify(u << 1 | 1, x, v);
    		push_up(u);
    	}
    }
    
    pair<int, int> query(int u, int l, int r) {
    	if (l <= tr[u].l && tr[u].r <= r) {
    		return { tr[u].sum, tr[u].pre_min };
    	}
    	else {
    		int mid = tr[u].l + tr[u].r >> 1;
    		pair<int, int> left = { 0, 0 };
    		if (l <= mid) left = query(u << 1, l, r);
    		pair<int, int> right = { 0, 0 };
    		if (r > mid) right = query(u << 1 | 1, l, r);
    		//auto right = query(u << 1 | 1, l, r);
    		return { left.first + right.first, min(left.second, left.first + right.second) };
    	}
    }
    
    int main() {
    	int n, q;
    	string s;
    	cin >> n >> q;
    	cin >> s;
    	for (int i = 0; i < n; i++) W[i + 1] = (s[i] == '(' ? 1 : -1);
    	build(1, 1, n);
    	while (q--) {
    		int op, l, r;
    		cin >> op >> l >> r;
    		if (op == 1) {
    			swap(W[l], W[r]);
    			modify(1, l, W[l]), modify(1, r, W[r]);
    		}
    		else {
    			auto t = query(1, l, r);
    			if (t.first == 0 && t.second >= 0) puts("Yes");
    			else puts("No");
    		}
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    什么样的代码称得上是好代码?
    九年程序人生 总结分享
    Docker入门 第一课 --.Net Core 使用Docker全程记录
    阿里云 Windows Server 2012 r2 部署asp.net mvc网站 平坑之旅
    Visual studio 2015 Community 安装过程中遇到问题的终极解决
    Activiti6.0 spring5 工作流引擎 java SSM流程审批 项目框架
    java 进销存 库存管理 销售报表 商户管理 springmvc SSM crm 项目
    Leetcode名企之路
    24. 两两交换链表中的节点
    21. 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/15451884.html
Copyright © 2011-2022 走看看