CF286C Main Sequence 题解
题目链接
题目大意
定义一个“整数括号序列”:每个正整数都要有一个与之匹配的相反数,把正整数视为左括号,负整数视为右括号...
设\(lsum_i\),\(rsum_i\)为位置\(1\)~\(i\)的左、右括号数量,则这个序列要求每个左(右)括号都有对应的右(左)括号。
现在给你\(N\)个正整数,给定其中\(M\)个位置,对其取负,问能否将另一些位置的正整数也取负,使得这个“整数括号序列”合法。如果可以,输出这个修改后的序列。
\(N\le 10^6,M\le N\)
输入格式
第一行一个\(N\),接下来一行\(N\)个正整数,下面一行一个\(M\),然后\(M\)个数\(q_i\)紧接其后,表示将\(a_{q_i}\)变成原来的数的相反数。
输出格式
如果不能把更改后的数组变得合法,就输出NO,否则输出YES,并且输出更改后的合法序列。
思路
我们从右往左贪心(因为我们要根据右括号去匹配左括号),然后如果当现在的\(a_i< 0\)我们就把它推到当前的栈里,如果遇到了一个正整数,那就看看这个数跟栈顶匹不匹配,匹配就pop掉栈顶,否则我们就把当前这个正整数变为它的相反数,然后也推进栈里面,试着跟后面的正整数匹配。
如果栈不空,那么就匹配不了,就输出NO,否则输出YES,然后再把我们刚刚的\(a\)数组输出即珂。
\(ACcode\)
#include<bits/stdc++.h>
#define F(i,l,r) for(register int i=l;i<=r;i++)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define p_b push_back
#define m_p make_pair
#define il inline
using namespace std;
int n,m;
int a[1000005],q;
stack<int> S;
int main() {
scanf("%d",&n);
F(i,1,n) scanf("%d",&a[i]);
scanf("%d",&m);
F(i,1,m) scanf("%d",&q),a[q]=-a[q];
for(int i=n;i>0;i--) {
if(a[i]>=0&&!S.empty()&&S.top()==-a[i]) S.pop();
else S.push(a[i]*=a[i]>0?-1:1);
}
if(!S.empty()) return puts("NO"),0;
puts("YES");
F(i,1,n) printf("%d ",a[i]);
return 0;
}

浙公网安备 33010602011771号