专栏文章
题解:CF2143E Make Good
CF2143E题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minulimc
- 此快照首次捕获于
- 2025/12/02 08:36 3 个月前
- 此快照最后确认于
- 2025/12/02 08:36 3 个月前
简单构造题,但赛时被 D 卡了……
首先显然的是, 为奇数肯定无解,直接特判。
接下来尝试构造出合法序列。一个重要的观察是,如果有两个相邻的相同括号,那么它们可以被同时移动到任意处。
Proof
以两个相邻的左括号为例,只需要进行如下两次操作即可做一次平移:
由于左右括号可以相互变化,因此只需要统计相邻的相同括号总数,设为 且默认均变为一种类型的括号。先把它们统一移到一侧,则剩下的括号只会有两种情况:
-
将 个括号堆中的 个进行翻转即可。由于每次要翻转两个括号,所以 得是偶数,也就是 。构造变成 。
-
此时先要用 个括号把它变成 ,然后剩余和 情况同理。
代码如下:
CPPvoid solve ()
{
int n = read (),cnt = 0,d = 0;scanf ("%s",str + 1);
if (n & 1) {puts ("-1");return;}
stack <char> s;
for (int i = 1;i <= n;++i)
{
if (!s.empty () && s.top () == str[i]) cnt += 2,s.pop ();
else s.push (str[i]);
}
vector <int> ans;
while (!s.empty ()) ans.push_back (s.top ()),s.pop ();
if (!ans.empty () && *(--ans.end ()) == ')')
{
if (!cnt) {puts ("-1");return;}
else cnt -= 2,ans.push_back ('('),ans.push_back ('('),++d;
}
reverse (ans.begin (),ans.end ());
if (!ans.empty () && *(--ans.end ()) == '(')
{
if (!cnt) {puts ("-1");return;}
else cnt -= 2,ans.push_back (')'),ans.push_back (')'),--d;
}
if (d || (cnt & 3)) {puts ("-1");return;}
for (auto v : ans) printf ("%c",v);
for (int i = 1;i <= cnt / 2;++i) printf ("(");
for (int i = 1;i <= cnt / 2;++i) printf (")");
puts ("");
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...