题意简述
给定nnn,构造一个长度为2n2n2n的字符串(开了SPJ,一个即可),使得这个字符串是一个匹配的括号序列,并且第iii个左括号满足:它和它匹配的右括号之间的距离在[Li,Ri][L_i,R_i][Li,Ri]之间。无解输出IMPOSSIBLE。
数据
输入
4
1 1
1 1
1 1
1 1
输出
()()()()
输入
3
5 5
3 3
1 1
输出
((()))
输入
3
5 5
3 3
2 2
输出
IMPOSSIBLE
输入
3
2 3
1 4
1 4
输出
(())()
思路
括号序列的问题,我们很容易想到用栈模拟。每次我们把一个左括号丢进栈里面,然后如何处理匹配的右括号呢?
仔细想想,发现:如果能匹配,马上就配上一定是最优的\color{red}马上就配上一定是最优的马上就配上一定是最优的。因为如果我们不马上配上,过一会距离就越来越远,远到出了边界,就不合法了,答案就不如马上配上的情况优。
然后我们只要这样模拟一下即可。代码:
#include<bits/stdc++.h>
#define N 1300
using namespace std;
int l[N],r[N],n;
int pos[N];
char ans[N];
stack<int>sta;//栈
void Input()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&l[i],&r[i]);
}
}
void Construct()
{
int cnt=0;
bool flag=1;
for(int i=1;i<=n;i++)
{
sta.push(i);
pos[i]=cnt;
ans[cnt]='(';
++cnt;//加入一个左括号
while(sta.size())
{
int x=sta.top();
if (pos[x]+l[x]>cnt) break;
//距离过于短,在不断右移的过程中还珂能变长回来,所以只是break掉,以后在处理这个问题
if (pos[x]+r[x]<cnt)
{
flag=false;
break;
}
//但是距离过长就不一样了,以后的右移过程中只会越来越长,这样肯定是无解的,标记好
ans[cnt]=')';++cnt;
sta.pop();//配好一个右括号
}
}
ans[cnt]='\0';
if (flag and sta.empty())
//flag=0说明距离过于远
//!sta.empty()说明有的没有匹配上
//都是无解的情况
//所以flag and sta.empty()相当于判有解
{
puts(ans);//输出解
}
else
{
puts("IMPOSSIBLE");//无解
}
}
main()
{
Input();
Construct();
return 0;
}
本文探讨了一种构造括号序列的算法,通过栈模拟实现,确保每个左括号与其匹配的右括号间的距离符合预设范围,适用于解决特定的算法问题。

被折叠的 条评论
为什么被折叠?



