Codeforces #670 div2

A

水题,直接模拟能填就填。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 1e6+10;

ll N, M, T, t[MAXN];

int main() {
    scanf("%lld", &T);
    while (T--) {
        for (ll i = 0; i <= 100; i++) t[i] = 0;
        scanf("%lld", &N);
        for (ll tem, i = 1; i <= N; i++) {
            scanf("%lld", &tem);
            t[tem]++;
        }
        ll ans = 0;
        for (ll i = 0; i <= 100; i++) {
        	if (t[i]) {
        		t[i]--;	
        	} else {
        		ans += i;
        		break;
			}
        }
        for (ll i = 0; i <= 100; i++) {
        	if (t[i]) {
				t[i]--;
			} else {
				ans += i;
				break;	
			}
        }
        printf("%lld\n", ans);
    }
    return 0;
}

B

先排序,然后 前5个,前4个后1个,前3个后2个,前2个后3个,前1个后4个,后5个 六种方案取max就行。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 1e6+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;

ll N, T, val[MAXN];

ll Max(); 

int main() {
    scanf("%lld", &T);
    while (T--) {
        scanf("%lld", &N);
        for (ll i = 1; i <= N; i++) {
            scanf("%lld", val+i);
        }
        sort(val+1, val+N+1);
        ll ans = Max();
        printf("%lld\n", ans);
    }
    return 0;
}

ll Max() {
    ll ret = -INF;
    ret = max(val[1] * val[2] * val[3] * val[4] * val[5], ret);
    ret = max(val[1] * val[2] * val[3] * val[4] * val[N], ret);
    ret = max(val[1] * val[2] * val[3] * val[N-1] * val[N], ret);
    ret = max(val[1] * val[2] * val[N-2] * val[N-1] * val[N], ret);
    ret = max(val[1] * val[N-3] * val[N-2] * val[N-1] * val[N], ret);
    ret = max(val[N-4] * val[N-3] * val[N-2] * val[N-1] * val[N], ret);
    return ret;
}

C

直接找到重心,如果只有一个随便输出一条边两次就行。
否则在一个重心的子树切一根然后接到另一个重心上。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 1e6+10;

struct edge {
    ll nt, to;
} E[MAXN];

ll N, M, T, cnt = -1, head[MAXN], siz[MAXN], fa[MAXN], w[MAXN];
ll root, other, del;

void add(ll, ll);
void dfs(ll, ll);
ll gtl(ll);

int main() {
    scanf("%lld", &T);
    while (T--) {
        scanf("%lld", &N);
        root = 0, del = 0, other = 0;
        for (ll i = 1; i <= N; i++) {
            head[i] = -1;
            siz[i] = 0;
            w[i] = 0;
            fa[i] = 0;
        }
        cnt = -1;
        ll tem1, tem2;
        for (ll x, y, i = 1; i < N; i++) {
            scanf("%lld%lld", &x, &y);
            add(x, y);
            add(y, x);
            tem1 = x, tem2 = y;
        }
        dfs(1, 0);
        if (!other) {
            printf("%lld %lld\n", tem1, tem2);
            printf("%lld %lld\n", tem1, tem2);
        } else {
            if (fa[other] == root) swap(root, other);
        	ll del = gtl(root);
            printf("%lld %lld\n", del, fa[del]);
            printf("%lld %lld\n", del, other);
        }
    }
    return 0;
}

ll gtl(ll n) {
	bool flag = 0;
	for (ll i = head[n]; ~i; i = E[i].nt) {
		ll v = E[i].to;
		if (v == fa[n]) continue;
		else {
			return gtl(v);
			flag = 1;	
		}
	}
	if (!flag) return n; 
}

void dfs(ll n, ll ff) {
    fa[n] = ff;
    for (ll i = head[n]; ~i; i = E[i].nt) {
        ll v = E[i].to;
        if (v == ff) continue;
        else {
            dfs(v, n);
            siz[n] += siz[v];
            w[n] = max(w[n], siz[v]);
        }
    }
    siz[n]++;
    w[n] = max(w[n], N - siz[n]);
    if (root == 0 || w[root] > w[n]) root = n, other = 0;
    else if (w[root] == w[n]) other = n;
}

void add(ll x, ll y) {
    cnt++;
    E[cnt].to = y;
    E[cnt].nt = head[x];
    head[x] = cnt;
}

/*
1
5
1 2
2 3
3 4
2 5
18
1 2
1 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
2 11
11 12
11 13
2 14
14 15
2 16
16 18
16 17

*/

D

先差分,然后我们可以知道序列的最大值一定是 \(b_n\) 或者 \(c_1\) 那么我们就让这俩最接近就好。
那么我们可以考虑
\(a_i > a_{i-1}\)\(b_{i} = b_{i-1} + a_i - a_{i-1}\)
\(a_i < a_{i-1}\)\(c_{i} = c_{i-1} + a_i - a_{i-1}\)
那么我们令 \(K = \sum_{i=2}^N \max(a_i - a_{i-1}, 0)\)\(c_1 = x\)
那么 原题即为求解 \(\max(x, a_1-x+K)\)
那么我们令 \(x\)\(a_1-x+K\) 尽可能接近即可。
答案即为 \(\lceil \frac{a_1+K}{2} \rceil\)
对于一个修改,我们发现只会修改到 \(a_l-a_{l-1}\)\(a_{r+1} - a_r\) 的值
那么只需要在相应的位置修改并将影响加至 \(K\) 即可。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 1e6+10;

ll N, M, T, val[MAXN], del[MAXN], sum;

ll ans(ll);
void upd(ll, ll);

int main() {
    scanf("%lld", &N);
    for (ll i = 1; i <= N; i++) {
        scanf("%lld", val+i);
        del[i] = val[i] - val[i-1];
        if (i != 1 && del[i] > 0) sum += del[i];
    }
    printf("%lld\n", ans(val[1] + sum));
    scanf("%lld", &M);
    for (ll i = 1, l, r, d; i <= M; i++) {
        scanf("%lld%lld%lld", &l, &r, &d);
        if (l == 1) val[1] += d;
        else {
            upd(l, d);
        }
        if (r != N) {
            upd(r+1, -d);
        }
        printf("%lld\n", ans(val[1] + sum));
    }
    return 0;
}

void upd(ll pos, ll v) {
    ll bef = max(del[pos], 0LL);
    del[pos] += v;
    sum += max(del[pos], 0LL) - bef;
} 

ll ans(ll x) {
    if (x >= 0) return (x + 1) / 2;
    else return x / 2;
}
posted @ 2020-09-13 22:21  Gensokyo_Alice  阅读(63)  评论(1编辑  收藏  举报