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