题解 P8407 【COCI 2021/2022 #6 - Superpozicija】
这是可以算是一道反悔贪心的板子题。
题意简述
给出
解题思路
整个括号序列合法的充要条件为:在每一个位点之前的左括号数大于等于右括号数,且整个序列的左括号数等于右括号数。
记左括号为
所以我们对于一组相同的括号可以直接这样贪心地选择:两个左括号取左侧的那个,两个右括号取右侧的那个。
设合法前缀序列表示一个所有位点的前缀和都大于等于零的序列。
显然可知以下推论:一个合法前缀序列删去任意一个右括号或添加任意一个左括号后仍为合法前缀序列。
所以对于一组不同的括号可以总是先选择右括号。
从左到右遍历、选择。在每一个位点都需要判断前缀序列是否为合法前缀序列,遇到不合法的情况(因为每个点都判断,此时当前位点的前缀和为
如果之前选择了多组不同的括号,设左括号的位置为
AC 代码
#include<bits/stdc++.h>
using namespace std;
char s[200010];
int pos[200010],ab[100005][2],q[200010];
struct comp{
bool operator()(const pair<int,int>x,const pair<int,int>y)const{return max(x.first,x.second)>max(y.first,y.second);}
};
int main(){
int T;scanf("%d",&T);
while(T--){
int n,ans=0;scanf("%d%s",&n,s);
for(int i=0;i<n;i++){
q[i<<1]=q[(i<<1)|1]=0;
scanf("%d%d",&ab[i][0],&ab[i][1]);
--ab[i][0];--ab[i][1];
pos[pos[ab[i][0]]=ab[i][1]]=ab[i][0];
}
priority_queue<pair<int,int>,vector<pair<int,int> >,comp>r;
for(int i=0;i<n<<1;i++){
if(q[i]==0&&q[pos[i]]==0){
if(s[i]=='('){
if(s[pos[i]]=='(')q[i]=1;
else{
r.push(make_pair(i,pos[i]));
q[pos[i]]=-1;
}
}
else if(s[pos[i]]==')')q[pos[i]]=-1;
else{
r.push(make_pair(pos[i],i));
q[i]=-1;
}
}
if(q[i]!=0){
ans+=q[i];
if(ans<0){
if(r.empty())break;
pair<int,int>p=r.top();r.pop();
if(i>=p.second)ans++;
q[p.second]=0;
if(i>=p.first)ans++;
q[p.first]=1;
}
}
}
if(ans)puts("-1");
else{
for(int i=0;i<n;i++)printf("%d ",q[ab[i][0]]?0:1);
putchar('\n');
}
}
return 0;
}