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;
}
posted @ 2020-10-06 22:38  moonlateQZ  阅读(79)  评论(0)    收藏  举报