Codeforces Round #620 (Div. 2)
A:a + b整除y - x的时候可以跳到一起。
int main() {
int t; scanf("%d", &t);
while(t --) {
int x, y, a, b;
scanf("%d%d%d%d", &x, &y, &a, &b); y -= x;
printf("%d
", y % (a + b) == 0 ? (y / (a + b)) : -1);
}
return 0;
}
B:因为串长都一样所以好做。如果是本身是回文串,出现了奇数次就拿一个放中间,其他放两边。如果不是回文串但原串和反串各出现x, y次,两边接上min(x, y)对。
int n, m, f[N], g[N];
char s[110][110];
bool same(int u, int v) {
for(int i = 1; i <= m; i ++)
if(s[u][i] != s[v][i]) return 0;
return 1;
}
bool rev(int u, int v) {
for(int i = 1; i <= m; i ++)
if(s[u][i] != s[v][m - i + 1]) return 0;
return 1;
}
void print(int u) {
printf("%s", s[u] + 1);
}
void pf(int u) {
for(int i = m; i >= 1; i --) putchar(s[u][i]);
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) {
scanf("%s", s[i] + 1);
bool t = 0;
for(int j = 1; j < i; j ++) {
if(same(i, j)) { f[j] ++; t = 1; break ; }
if(rev(i, j)) { g[j] ++; t = 1; break ; }
}
if(t) { i --; n --; continue ; }
f[i] = 1;
}
int len = 0, mid = 0, midx;
vector<int> ans;
for(int i = 1; i <= n; i ++) {
if(rev(i, i)) {
len += 2 * m * (f[i] / 2);
for(int j = f[i] / 2; j >= 1; j --)
ans.push_back(i);
if(f[i] % 2 == 1) { mid = 1; midx = i; }
} else {
for(int j = min(f[i], g[i]); j >= 1; j --)
ans.push_back(i);
len += 2 * m * min(f[i], g[i]);
}
}
printf("%d
", len + mid * m);
for(int i = 0; i < (int) ans.size(); i ++) print(ans[i]);
if(mid) print(midx);
for(int i = (int) ans.size() - 1; i >= 0; i --) pf(ans[i]);
return 0;
}
C:每次维护一个区间,表示这个区间里的温度都可以达到。如果发现上一轮的区间转移不到当前要求区间就NO。
struct Node { int t, l, r; } a[N];
int q, n, m;
int main() {
scanf("%d", &q);
while(q --) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
scanf("%d%d%d", &a[i].t, &a[i].l, &a[i].r);
int ql = m, qr = m; bool fail = 0;
for(int i = 1; i <= n; i ++) {
int nl = a[i].l, nr = a[i].r, dt = a[i].t - a[i - 1].t;
if(nr < ql - dt || nl > qr + dt) { fail = 1; break ; }
ql -= dt; qr += dt; ql = max(ql, nl); qr = min(qr, nr);
}
puts(fail ? "NO" : "YES");
}
return 0;
}
D:
LIS最短:容易知道答案>= max(连续'<'长度) + 1.可以构造出恰等于的情况:每次分一个连续段从最大的一段取。
LIS最长:容易知道答案<= max('<'个数 + 1, '>'段个数)。容易知道前者更大,于是构造恰等于'<'个数 + 1的排列:维护l, r初始为1,p[1] = 1。若是小于就分配++ r否则分配-- l,最后在把值域换成[1, n],显然正确。当然也可以仿照LIS最短做。
int n, x[N], ans[N];
char s[N];
int main() {
int t; scanf("%d", &t);
while(t --) {
scanf("%d%s", &n, s + 2);
int l = 1, r = n;
for(int i = 2; i <= n; ) {
int j = i;
for(; j < n && s[j + 1] == s[i]; j ++) ;
if(s[i] == '<') {
for(int k = j; k >= i; k --) x[k] = r --;
if(i == 2) x[1] = r --;
else {
int t = x[i - 1];
for(int k = i; k <= j; k ++) x[k - 1] = x[k];
x[j] = t;
}
} else {
if(i == 2) x[1] = r --;
for(int k = i; k <= j; k ++) x[k] = r --;
}
i = j + 1;
}
for(int i = 1; i <= n; i ++) printf("%d%c", x[i], "
"[i == n]);
x[1] = 1; l = 1, r = 1; int mp = 1;
for(int i = 2; i <= n; i ++) {
if(s[i] == '<') x[i] = ++ r;
else x[i] = -- l;
mp = min(mp, x[i]);
}
if(mp != 1) { for(int i = 1; i <= n; i ++) x[i] -= mp - 1; }
for(int i = 1; i <= n; i ++) printf("%d%c", x[i], "
"[i == n]);
}
return 0;
}
E:我们只需求出a->b,a->x->y->b, a->y->x->b这三条路径是不是 + 2N = k。
bool ok(int x, int y) {
return x <= y && (y - x) % 2 == 0;
}
int main() {
scanf("%d", &n);
for(int i = 1; i < n; i ++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].pb(v); G[v].pb(u);
}
dfs(1, 0);
scanf("%d", &q);
for(int i = 1; i <= q; i ++) {
int x, y, a, b, k;
scanf("%d%d%d%d%d", &x, &y, &a, &b, &k);
int d = dis(a, b); bool tag = 0;
if(ok(d, k)) tag = 1;
if(ok(dis(a, x) + dis(b, y) + 1, k)) tag = 1;
if(ok(dis(a, y) + dis(b, x) + 1, k)) tag = 1;
puts(tag ? "YES" : "NO");
}
return 0;
}
F:dp[i][j]表示前i行的答案,其中第i行选[i, j]。单调队列转移
const int N = 62, M = 4e4 + 10;
int n, m, k, a[N][M], s[N][M], dp[N][M];
int calc(int x, int y) {
return s[x][y + k - 1] - s[x][y - 1] + s[x + 1][y + k - 1] - s[x + 1][y - 1];
}
int main() {
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) scanf("%d", &a[i][j]);
for(int j = 1; j <= m + k; j ++) s[i][j] = s[i][j - 1] + a[i][j];
}
for(int i = 1; i <= m; i ++) dp[1][i] = calc(1, i);
static int q[M], l, r;
for(int i = 2; i <= n; i ++) {
l = r = 0; int Max = -2e9;
for(int j = 1; j <= m; j ++) {
if(j - k >= 1) Max = max(Max, dp[i - 1][j - k]);
while(l < r && dp[i - 1][q[r - 1]] - s[i][q[r - 1] + k - 1] <= dp[i - 1][j] - s[i][j + k - 1]) r --;
q[r ++] = j;
while(l < r && q[l] + k - 1 < j) l ++;
dp[i][j] = calc(i, j) + max(Max, dp[i - 1][q[l]] - s[i][q[l] + k - 1] + s[i][j - 1]);
}
l = r = 0; Max = -2e9;
for(int j = m; j >= 1; j --) {
if(j + k <= m) Max = max(Max, dp[i - 1][j + k]);
while(l < r && dp[i - 1][q[r - 1]] + s[i][q[r - 1] - 1] <= dp[i - 1][j] + s[i][j - 1]) r --;
q[r ++] = j;
while(l < r && q[l] >= j + k) l ++;
dp[i][j] = max(dp[i][j], calc(i, j) + max(Max, dp[i - 1][q[l]] + s[i][q[l] - 1] - s[i][j + k - 1]));
}
}
int ans = 0;
for(int i = 1; i <= m; i ++) ans = max(ans, dp[n][i]);
printf("%d
", ans);
return 0;
}