洛谷传送门
CF传送门
解题思路
先考虑没有限制负数的情况,很显然就是用一个栈,每次与栈顶能配对就配对。
当有限制负数时,会出现错误,如 1 1 3 3 -1 -1,此时我们不能让前两个1相配对。
这是进行以下两个改动:
- 因为要求是正数在负数前面,所以我们进行倒序枚举。
- 若当前数要求为负数,则直接入栈。若为正数且与栈顶能配对,则直接配对,并把栈顶定为负数。
最后如果栈为空,则最终可以配对成功,否则不成功。
AC代码
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<iomanip> 5 #include<cmath> 6 #include<stack> 7 using namespace std; 8 const int maxn=1000005; 9 stack<int> s; 10 int n,m,a[maxn],vis[maxn]; 11 int main(){ 12 cin>>n; 13 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 14 cin>>m; 15 for(int i=1;i<=m;i++){ 16 int x; 17 scanf("%d",&x); 18 vis[x]=1; 19 } 20 for(int i=n;i>=1;i--){ 21 if(s.empty()){ 22 s.push(i); 23 }else{ 24 if(vis[i]) s.push(i); 25 else if(a[i]==a[s.top()]){ 26 if(vis[i]==0){ 27 vis[i]=1; 28 vis[s.top()]=-1; 29 s.pop(); 30 }else{ 31 s.push(i); 32 } 33 }else{ 34 s.push(i); 35 } 36 } 37 } 38 if(!s.empty()){ 39 cout<<"NO"<<endl; 40 }else{ 41 cout<<"YES"<<endl; 42 for(int i=1;i<=n;i++) cout<<a[i]*vis[i]<<" "; 43 } 44 return 0; 45 }