C. Compressed Bracket Sequence (思维,暴力,好题)

PS:这题官方给的题解可能因为自己英语太差了没看懂。。。比赛时候写了个DP被卡了,看了好久才看懂大佬的代码,原来就是个暴力。。。

大致思路:先统计出两两配对的答案数,再对剩余的左括号暴力向后找能配对的右括号,还要统计一下以当前括号为起点可以向后连接多少个括号。直接看代码吧,注释写的很详细。

另外这题代码其实可以很短(根据官方题解给的结论,十行左右吧),感兴趣的同学可以去看官方题解。

#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=1e6+5,INF=1e16;
int n;
int s[N];
 
void solve() {
	cin>>n;
	for(int i=1;i<=n;i++)cin>>s[i];
	
	int res=0;
	
	//先将两两一组可以匹配的括号匹配掉,剩下的括号数组一定是x 0 0 y或者 x 0 y 0等等这种(每两个一定会有一个0) 
	for(int i=1;i<=n;i+=2){
		int k=min(s[i],s[i+1]);
		res+=k;
		s[i]-=k,s[i+1]-=k;
	} 
	
	//固定当前按i的剩余的左括号,计算对于当前的剩余的左括号 后面能有多少个剩余的右括号能匹配上 
	for(int i=1;i<=n;i+=2){
		if(s[i+1])continue;//如果是0 x 这种说明没有剩余的左括号,直接跳过 
		
		int l=s[i],d=s[i],mx=s[i];//l表示当前未配对左括号的数量 ,mx表示遍历后方所有括号的过程中最多有多少左括号不能匹配 
		int sum=0;  
		
		for(int j=i+3;j<=n;j+=2){ 
			sum+=s[j-1]-s[j];
			
			if(sum<0)sum=0;//如果是 x 0 0 y这种(s[j-1]=0,s[j]=y),显然x 0 ,0 y这两块已经配 对的左括号可以连在一起 
			if(sum==0)res++;//之前已经配对的括号对可以连在一起,答案++
			
			if(s[j]){//如果有右括号,说明可以跟之前的左括号配对 
				d-=s[j];
				mx=min(mx,d);
				if(d<0){
					mx=0;//如果d<0说明右括号数量大于左括号数量,前面所有的左括号都能匹配,不会有剩余 
					break;
				} 
			}
			
			d+=s[j-1];//d表示当前还剩余多少未匹配的左括号 
		}
		
		res+=l-mx;//l-mx对于i点的左括号,后面能跟这些左括号匹配的最大个数 
	}
	
	cout<<res<<endl; 
}

main(){
	ios_base::sync_with_stdio(false), cin.tie(nullptr);
	//init();
	solve();
}```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值