ARC120 VP 记录

A

对于每个序列,发现第一次改变了 \(a_1\) 的时候最大值就成了 \(a_1\),然后第 \(i\) 次改变后最大值就是 \(a_i\),然后随便分析一下每个元素对最终答案的贡献即可,可以做到 \(\mathcal O(n)\)

B

把棋盘逆时针倾斜 \(45^\circ\) ,然后每走一步相当于都相当于向右走,如果一斜行上的颜色不同,方案数就 \(\times 0\),如果都是 ?,方案数 \(\times 2\)。其他情况方案数不变。

为什么正确?(好像是个套路的转换方式)

如果有颜色不一样的,那肯定有一个位置的下一步是两个不同的颜色,然后不管其他步走了什么,只要分别走这两个不同的颜色,一定有一个方案是不合法的。

C

怎样判断有无解,让 \(a_i \to a_i + i, b_i \to b_i + i\),如果数量和值域对应相等就有解,否则无解。

(就考虑把他们都移到 \(0\) 这个位置,然后再分配回去。)

至于有解的情况,按照贪心去模拟即可。

可以借助树状数组和 set 实现。

复杂度 \(\mathcal O(n \log n)\)

D

Orz lzy

考虑什么情况下答案最优,最大的 \(n\) 个和最小的 \(n\) 个匹配。

然后我们就让最大的 \(n\) 个和最小的 \(n\) 个匹配。

首先要知道这一定存在合法解。

然后通过栈模拟确定谁是左括号谁是右括号即可。

E

题解没看懂呜呜呜

大概有个结论就是:我们把一开始就相互奔赴的两个元素看作一对,相邻两对之间不会超过一个元素。

然后 dp 求 max 即可。

/*
Work by: Suzt_ilymtics
Problem: 不知名屑题
Knowledge: 垃圾算法
Time: O(能过)
*/
#include<bits/stdc++.h>
#define LL long long
#define orz cout<<"tyy YYDS!!!\n"

using namespace std;
const int MAXN = 2e5+5;
const int INF = 1e9+7;
const int mod = 1e9+7;

int n;
int a[MAXN];
int f[MAXN];

int read() {
    int s = 0, f = 0;
    char ch = getchar();
    while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0', ch = getchar();
    return f ? -s : s;
}

int main()
{
    n = read();
    for(int i = 1; i <= n; ++i) a[i] = read();
    a[0] = a[1], a[n + 1] = a[n];
    for(int i = 2; i <= n; ++i) {
        f[i] = a[i + 1] - a[0];
        for(int j = i - 1; j > i - 4; -- j) {
            f[i] = min(f[i], max(f[j - 1], a[i + 1] - a[j - 1]));
        }
    }
    printf("%d\n", f[n] / 2);
    return 0;
}
posted @ 2022-03-04 08:57  Suzt_ilymtics  阅读(40)  评论(0编辑  收藏  举报