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\n", 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\n", 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], " \n"[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], " \n"[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:

猜你喜欢

转载自www.cnblogs.com/hongzy/p/12316419.html