Codeforces Round #595 (Div. 3)

A
若i存在i-1,i+1时即必须分2组,其余1组

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int maxn = 1e2 + 5;
int a[maxn];
int cnt[maxn];
int main()
{
    int q; cin >> q;
    while (q--) {
        int n; cin >> n;
        memset(cnt, 0, sizeof(cnt));
        bool flg = false;
        for (int i = 1; i <= n; ++i) {
            int x; cin >> x;
            if (cnt[x - 1] || cnt[x + 1]) flg = true;
            cnt[x] = 1;
        }
        if (flg) cout << 2 << endl;
        else cout << 1 << endl;
    }
}

B
无向图缩点若干个联通块,每个联通块里面即是联通块大小

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
vector<int> E[maxn];
stack<int> stk;
int dfn[maxn], low[maxn], tot, vis[maxn], color, clr[maxn], cnt[maxn];
void tarjan(int u) {
    dfn[u] = low[u] = ++tot;
    stk.push(u);
    vis[u] = 1;
    for (int i = 0; i < E[u].size(); ++i) {
        int v = E[u][i];
        if (vis[v] == 0) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if (vis[v] == 1)
            low[u] = min(low[u], dfn[v]);
    }
    if (dfn[u] == low[u]) {
        int v; color++;
        do {
            v = stk.top(); stk.pop();
            vis[v] = -1;
            clr[v] = color;
            cnt[color]++;
        } while (v != u);
    }
}
int main()
{
    int q; scanf("%d", &q);
    while (q--) {
        int n; scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            int x; scanf("%d", &x);
            E[i].push_back(x);
        }
        for (int i = 1; i <= n; ++i)
            if (dfn[i] == 0) tarjan(i);
        for (int i = 1; i <= n; ++i) {
            if (i != 1) putchar(' ');
            printf("%d", cnt[clr[i]]);
        }
        putchar('\n');
        for (int i = 1; i <= color; ++i) cnt[i] = 0;
        tot = color = 0;
        while (!stk.empty()) stk.pop();
        for (int i = 1; i <= n; ++i) {
            E[i].clear();
            dfn[i] = low[i] = vis[i] = clr[i] = 0;
        }
    }
}

C
队友过题

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int maxn = 100 + 5;
typedef long long ll;
int a[maxn];
int main()
{
	ios::sync_with_stdio(false); cin.tie(0);
	int t; cin >> t;
	while(t--)
	{
	    for (int i = 1; i <= 50; ++i) a[i] = 0;
	    ll n; cin >> n;
		int tot = 0;
		while(n)
		{
			a[++tot] = n % 3;
			n /= 3;
		}
		bool flg = false; int i, j = 1;
		for(i = tot; i >= 1; i--)
		{
		    if (a[i] > 1) { flg = true; break; }
		}
		if (flg) {
            for (j = i; j <= tot + 1; ++j) {
                if (a[j] == 0) break;
            }
            a[j] = 1;
		}
		ll tmp = 1, ans = 0;
		for (i = 1; i < j; i++) tmp *= 3;
		for (i = j; i <= tot + 1; ++i) {
            if (a[i] == 1) ans += tmp;
            tmp *= 3;
		}
		cout << ans << endl;
	 }
	 return 0;
}

D
把问题反向,即选择最多的线段使交点小于等于k
贪心:按线段r排序,用线段树维护交点个数

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <queue>
#include <map>
using namespace std;
#define endl '\n'
typedef long long ll;
const int maxn = 2e5 + 5;
int cnt[maxn << 2], lzy[maxn << 2], n, m;
void pushup(int rt) {
    cnt[rt] = max(cnt[rt << 1], cnt[rt << 1 | 1]);
}
void pushdown(int rt) {
    if (!lzy[rt]) return;
    cnt[rt << 1] += lzy[rt]; cnt[rt << 1 | 1] += lzy[rt];
    lzy[rt << 1] += lzy[rt]; lzy[rt << 1 | 1] += lzy[rt];
    lzy[rt] = 0;
}
void build(int rt = 1, int l = 1, int r = m) {
    if (l == r) {
        cnt[rt] = 0;
        return;
    }
    lzy[rt] = 0;
    int mid = (l + r) >> 1;
    build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r);
    pushup(rt);
}
void update(int L, int R, int val, int rt = 1, int l = 1, int r = m) {
    if (L <= l && r <= R) {
        cnt[rt] += val; lzy[rt] += val;
        return;
    }
    pushdown(rt);
    int mid = (l + r) >> 1;
    if (L <= mid) update(L, R, val, rt << 1, l, mid);
    if (mid < R) update(L, R, val, rt << 1 | 1, mid + 1, r);
    pushup(rt);
}
int query(int L, int R, int rt = 1, int l = 1, int r = m) {
    if (L <= l && r <= R) return cnt[rt];
    pushdown(rt);
    int mid = (l + r) >> 1, res = 0;
    if (L <= mid) res = max(res, query(L, R, rt << 1, l, mid));
    if (mid < R) res = max(res, query(L, R, rt << 1 | 1, mid + 1, r));
    pushup(rt);
    return res;
}
struct In {
    int l, r, id;
    bool operator <(const In& x) const {
        return r < x.r;
    }
} in[maxn];
vector<int> ans;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k; cin >> n >> k;
    for (int i = 1; i <= n; ++i) {
        cin >> in[i].l >> in[i].r;
        m = max(m, in[i].r); in[i].id = i;
    }
    sort(in + 1, in + n + 1);
    build();
    for (int i = 1; i <= n; ++i) {
        int res = query(in[i].l, in[i].r);
        if (res < k) update(in[i].l, in[i].r, 1);
        else ans.push_back(in[i].id);
    }
    cout << ans.size() << endl;
    for (int i = 0; i < ans.size(); ++i) {
        if (i > 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;
}

E
简单dp,dp[i][0]保持达到i时通过走楼梯到达,dp[i][1]表示到达i时通过电梯到达
状态转移:dp[i][0] = max(dp[i][0], a[i]+max(dp[i-1][0], dp[i-1][1])); dp[i][1] = max(dp[i][1], b[i]+max(dp[i-1][0]+c, dp[i-1][1]));

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <queue>
#include <map>
using namespace std;
#define endl '\n'
typedef long long ll;
const int maxn = 2e5 + 5;
int dp[maxn][2];
int a[maxn], b[maxn];
int main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    int n, c; cin >> n >> c;
    dp[0][0] = 0; dp[0][1] = 0x3f3f3f3f;
    for (int i = 1; i <= n - 1; ++i) cin >> a[i];
    for (int i = 1; i <= n - 1; ++i) cin >> b[i];
    for (int i = 1; i <= n - 1; ++i) {
        dp[i][0] = min(dp[i - 1][0] + a[i], dp[i - 1][1] + a[i]);
        dp[i][1] = min(dp[i - 1][0] + c + b[i], dp[i - 1][1] + b[i]);
    }
    for (int i = 0; i <= n - 1; ++i) {
        if (i != 0) cout << " ";
        cout << min(dp[i][0], dp[i][1]);
    }
    cout << endl;
}

F
按拓扑序反向,选择了某个节点i后,将它距离在k之内的点权值更改为a[j]-a[i]。若遍历到a[j]时仍然大于0表示选择j的贡献大于i

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define endl '\n'
typedef long long ll;
using namespace std;
const int maxn = 200 + 5;
int n, k;
int a[maxn], vis[maxn];
vector<int> E[maxn], vec;
void bfs() {
    queue<pair<int, int> > q;
    q.push(make_pair(1, 0));
    while (!q.empty()) {
        int u = q.front().first, dep = q.front().second;
        vec.push_back(u); q.pop();
        vis[u] = 1;
        for (int i = 0; i < E[u].size(); ++i) {
            int v = E[u][i]; if (vis[v]) continue;
            q.push(make_pair(v, dep + 1));
        }
    }
}
int num;
void dfs(int u, int fa, int dep) {
    if (dep > k) return;
    a[u] -= num;
    for (int i = 0; i < E[u].size(); ++i) {
        int v = E[u][i]; if (v == fa) continue;
        dfs(v, u, dep + 1);
    }
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> n >> k;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    for (int i = 1; i < n; ++i) {
        int u, v; cin >> u >> v;
        E[u].push_back(v);
        E[v].push_back(u);
    }
    bfs();
    int ans = 0; reverse(vec.begin(), vec.end());
    for (int i = 0; i < vec.size(); ++i) {
        if (a[vec[i]] <= 0) continue;
        ans += (num = a[vec[i]]);
        dfs(vec[i], vec[i], 0);
    }
    cout << ans << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值