# Educational Codeforces Round 151 (Rated for Div. 2) 感想

5 篇文章 0 订阅

## A. Forbidden Integer

### 3.代码


int main() {
cin >> t;
while (t--) {
ll k, x;
cin >> n >> k >> x;
vector<ll> ans;
if (x != 1) {
cout << "YES\n";
cout << n << "\n";
for (int i = 1; i <= n; i++) {
cout << "1 ";
}
cout << "\n";
}
else {
if (n % 2 == 0) {
if (k < 2) {
cout << "NO\n";
}
else {
cout << "YES\n";
cout << n / 2 << "\n";
for (int i = 1; i <= n / 2; i++) {
cout << "2 ";
}
cout << "\n";
}
}
else {
if (k < 3) {
cout << "NO\n";
}
else {
cout << "YES\n";
cout << n / 2 << "\n";
for (int i = 1; i <= n / 2 - 1; i++) {
cout << "2 ";
}
cout << "3\n";
}
}
}
}
return 0;
}


## B. Come Together

### 3.代码


int main() {
cin >> t;
while (t--) {
ll x, y;
cin >> x >> y;
ll a, b, c, d;
cin >> a >> b;
cin >> c >> d;
ll bx = (x - a), by = (y - b);
ll cx = (x - c), cy = (y - d);
if (bx * cx <= 0 && by * cy <= 0) {
cout << "1\n";
}
else if (bx * cx <= 0 && by * cy > 0) {
cout << min(abs(by), abs(cy)) + 1 << "\n";
}
else if (bx * cx > 0 && by * cy <= 0) {
cout << min(abs(bx), abs(cx)) + 1 << "\n";
}
else if (bx * cx > 0 && by * cy > 0) {
cout << min(abs(bx), abs(cx)) + min(abs(cy), abs(by)) + 1 << "\n";
}
}
return 0;
}


### 3.代码


ll t, n, m, p = 998244353;
ll arr[200005], sum[300005][10];
set<ll> pos[10];

int main() {
cin >> t;
while (t--) {
string s;
cin >> s;
n = s.size();
cin >> m;
string l, r;
cin >> l >> r;
for (int i = 0; i < 10; i++) {
pos[i].clear();
sum[0][i] = 0;
}
for (int i = 0; i < n; i++) {
ll tmp = s[i] - '0';
pos[tmp].insert(i);
}
bool ans = false;
ll ma = -1, mp = -1, now = -1;
for (int i = 0; i < m; i++) {
for (int j = l[i] - '0'; j <= r[i] - '0'; j++) {
auto x = pos[j].upper_bound(now);
if (x == pos[j].end()) {
ans = true;
break;
}
if (*x > ma) {
ma = *x;
mp = j;
}
}
if (ans) break;
now = ma;
}
if (ans) {
cout << "YES\n";
}
else {
cout << "NO\n";
}
}
return 0;
}


## D - Rating System

### 2.个人思路

dp转移，k的值为前i个数字的前缀和，最大值的对应k集合中一定至少会有一个1~x的前缀和。

dp[i]为以1~i - 1的前缀和为k（i == 1 时为0）时，i到n的变化让rating带来的提升。（为什么不是真正的提升，因为假设1 ~ i - 1的前缀和为x，在i - 1之前可能已经到达或者超过过x，那么这个结果就不好算了，而且实际上最优情况下1 ~ i - 1不应该存在超过前缀和的点，所以说dp的转移是正确的。）

dp[i] = abs(arr[i])

dp[i] = dp[low] - (sum[low - 1] - sum[i - 1])

### 3.代码

ll t, n, m, p = 998244353;
ll arr[300005], sum[300005];
ll dp[300005], low[300005];

int main() {
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
low[i] = 0;
sum[i] = sum[i - 1] + arr[i];
}
ll k = 0, nn = -1;
stack<ll> sto;
for (int i = 1; i <= n; i++) {
while (!sto.empty() && sum[sto.top()] > sum[i]) {
low[sto.top()] = i;
sto.pop();
}
sto.push(i);
}
for (int i = n; i > 0; i--) {
if (arr[i] > 0) {
dp[i] = -1;
}
else {
if (low[i]) {
dp[i] = dp[low[i]] - sum[low[i] - 1] + sum[i - 1];
}
else dp[i] = abs(arr[i]);
}
}
for (int i = 1; i <= n; i++) {
if (nn < dp[i]) {
nn = dp[i];
k = sum[i - 1];
}
}
cout << k << "\n";
}
return 0;
}


## 其他想法

D的转移并非当前状态的真正最优解，只是使用局部最优来处理，我也不知道对不对，急了就开始魔怔了。

• 3
点赞
• 0
收藏
觉得还不错? 一键收藏
• 0
评论
07-10 2536
06-30 345
12-06 1186
06-13 321
07-01 175
08-06 425
08-06 941
08-08 250
08-06 191

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。