codeforces div2 603 E. Editor(线段树)

题目链接:https://codeforces.com/contest/1263/problem/E

题意:一个编译器,每次输入一些字符,R表示光标右移,L表示光标左移,然后有一些左括号(  和 右括号 ),每次会询问当前输入的数据的括号是否合法,如果不合法输出-1,如果合法输出最大合法的括号对数,合法的括号就是()这种形式的。

思路:大致思路是用线段树维护区间一个区间前缀和,初始化前缀和为0。遇到单点更新,(让管辖区间+1,)就让管辖区间-1,,判断是否是合法括号需要判断区间最小值是否为0,且保证1到n区间的前缀和为0(画图思考一下),满足两种条件的同时才能说明此为合法括号序列,最终查询区间最大值就是最大匹配的括号对数(画图思考)。

代码:

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<set>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int maxn = 1e6+10;
struct node{
	int l,r;
	int Min,Max;
	int val;
	int lazy; 
}tree[maxn*4+5];
void pushdown(int index){
    if(tree[index].lazy){
        tree[index<<1].val += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].lazy;
        tree[index<<1|1].val +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].lazy;
        tree[index<<1].Max += tree[index].lazy;
        tree[index<<1|1].Max += tree[index].lazy;
        tree[index<<1].Min += tree[index].lazy;
        tree[index<<1|1].Min += tree[index].lazy;
        tree[index<<1].lazy += tree[index].lazy;
        tree[index<<1|1].lazy += tree[index].lazy;
        tree[index].lazy = 0;
    }
}
void pushup(int index){
    tree[index].val = tree[index<<1].val+tree[index<<1|1].val;
    tree[index].Max = max(tree[index<<1].Max,tree[index<<1|1].Max);
    tree[index].Min = min(tree[index<<1].Min,tree[index<<1|1].Min);
}

void build(int l,int r,int index){//建树  
	tree[index].l = l,tree[index].r = r,tree[index].lazy = 0;
	if(l == r){
        //scanf("%d",&tree[index].val);
        tree[index].val = 0;
        tree[index].Max = tree[index].Min = tree[index].val;
        return;
    }
	int mid = (l+r)>>1;//
    build(l,mid,index<<1);
    build(mid+1,r,index<<1|1);
    pushup(index);
} 
void update(int l,int r,int index,int val){//区间修改 
	if(l <= tree[index].l && r >= tree[index].r){
        tree[index].val += (tree[index].r-tree[index].l+1)*val;
        tree[index].Max += val;
        tree[index].Min += val;
        tree[index].lazy += val;//延时标记
        return ;
	}
	pushdown(index);
    int mid = (tree[index].l+tree[index].r)>>1;
    if(l <= mid){
        update(l,r,index<<1,val);
    }
    if(r > mid){
        update(l,r,index<<1|1,val);
    }
    pushup(index);
}

LL query_range(int l,int r,int index){//区间查询 
	if(l <= tree[index].l && r >= tree[index].r){
        return tree[index].val;
        //return tree[index].mn;
    }
    pushdown(index);
    int mid = (tree[index].l+tree[index].r)>>1;
    LL res = 0;
    LL Max = 0;
    LL Min = inf;
    if(l <= mid){
        res += query_range(l,r,index<<1);
    }
    if(r > mid){
        res += query_range(l,r,index<<1|1);
    }
    return res;
}

LL query_max(int l,int r,int index){//最大值查询 
	if(l<= tree[index].l && r>= tree[index].r ){
		return tree[index].Max;
	}
	pushdown(index);
	int mid = (tree[index].l + tree[index].r )>>1;
	LL ans = 0;
	LL MAX = 0,MIN = inf;
	if(l <= mid) MAX = max(query_max(l,r,index<<1),MAX);
	if(r > mid) MAX = max(query_max(l,r,index<<1|1),MAX);
	return MAX;
}
LL query_min(int l,int r,int index){//最小值查询 
	if(l<= tree[index].l && r>= tree[index].r ){
		return tree[index].Min;
	}
	pushdown(index);
	int mid = (tree[index].l + tree[index].r )>>1;
	LL ans = 0;
	LL MAX = 0,MIN = inf;
	if(l <= mid) MIN = min(query_min(l,r,index<<1),MIN);
	if(r > mid) MIN = min(query_min(l,r,index<<1|1),MIN);
	return MIN;
}
string s;
LL ss[maxn];
int main(){
	int n;
	scanf("%d",&n);
	n = n+10;
	build(1,n,1);
	cin>>s;
	int pos = 1;
	vector<int> ans;
	for(int i = 0;i<s.length() ;i++){
		if(s[i] == '('){
			update(pos,n,1,1-ss[pos]);
			ss[pos] = 1;
		}
		else if(s[i] == ')'){
			update(pos,n,1,-1-ss[pos]);
			ss[pos] = -1;
		}
		else if(s[i] == 'R'){
			pos++;
		}
		else if(s[i] == 'L'){
			if(pos>1) pos--;
		} 
		else{
			if(ss[pos] == 1){
				update(pos,n,1,-1);
			}
			else if(ss[pos] == -1){
				update(pos,n,1,1);
			}
			ss[pos] = 0;
		}
		if(query_min(1,n,1) == 0 && query_range(n,n,1) == 0){
			ans.push_back(query_max(1,n,1)); 
		}
		else{
			ans.push_back(-1); 
		}
	}
	for(int i = 0;i<ans.size() ;i++){
		cout<<ans[i]<<" ";
	}
	//cout<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值