题目大意:
给出一个长度为nnn的正整数序列sss。
规定其中的mmm个位置上的数必须符号取负,其他可正可负。
在满足条件的情况下构造一个序列AAA,需要满足:
对于一个AiA_iAi而言,
若Ai>0A_i>0Ai>0,则其充当一种特别的左括号,能与其匹配的右括号位置AjA_jAj,需要满足i<j,Aj=−Aii<j,A_j=-A_ii<j,Aj=−Ai
若Ai<0A_i<0Ai<0,则只能充当右括号
问能否构造出一个合法的AAA,若能,则输出任意一种合法AAA序列。
一开始会规定mmm个位置的A()A_{()}A()只能为负数。
n<=1e6,1<=si<=1e9n<=1e6,1<=s_i<=1e9n<=1e6,1<=si<=1e9
分析:
其实就是序号匹配问题,
考虑从右往左贪心即可
对当前位置,
①在限制中,丢入栈中,记为最新要匹配的右括号
②当前位置无法与栈顶匹配,丢入栈中,记为最新要匹配的右括号
③对钱位置可以与栈顶匹配,弹出栈顶
最后判断栈是否为空即可知道是否存在合法解
代码:
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
typedef long long ll;
int n, m, a[N];
vector<int>s;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
int t, x; scanf("%d", &t);
for (int i = 1; i <= t; i++) {
scanf("%d", &x); a[x] = -abs(a[x]);
}
for (int i = n; i >= 1; i--) {
if (a[i] < 0) s.push_back(-a[i]);
else if (!s.size()) s.push_back(a[i]), a[i] = -a[i];
else if (s[s.size()-1] == a[i]) s.pop_back();
else s.push_back(a[i]), a[i] = -a[i];
}
bool flag = (s.size()) ? 1: 0;
printf((!flag) ? "YES\n" : "NO\n");
if (!flag) {
for (int i = 1; i < n; i++) printf("%d ", a[i]); printf("%d", a[n]);
}
return 0;
}
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
typedef long long ll;
int n, m, a[N];
vector<int>s;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
int t, x; scanf("%d", &t);
for (int i = 1; i <= t; i++) {
scanf("%d", &x); a[x] = -abs(a[x]);
}
for (int i = n; i >= 1; i--) {
if (a[i] < 0) s.push_back(-a[i]);
else if (!s.size()) s.push_back(a[i]), a[i] = -a[i];
else if (s[s.size()-1] == a[i]) s.pop_back();
else s.push_back(a[i]), a[i] = -a[i];
}
bool flag = (s.size()) ? 1: 0;
printf((!flag) ? "YES\n" : "NO\n");
if (!flag) {
for (int i = 1; i < n; i++) printf("%d ", a[i]); printf("%d", a[n]);
}
return 0;
}