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;
}