20200926

T1 T2 都不想说,太傻比了, 是个人就会。
T3
对于没加入一条边如果连得两个点不在同一个联通块中并查集链接,记录练了多少条边
最后的时候用n-1减去连了多少条边,就是需要再连几条边。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define N 100010
#define M 1010
using namespace std;
int n, m, cnt;
int fath[N];
int read() {
int s = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
int father(int x) {
if (x != fath[x]) fath[x] = father(fath[x]);
return fath[x];
}
int main() {
n = read(), m = read();
for (int i = 1; i <= n; i++) fath[i] = i;
for (int i = 1, x, y; i <= m; i++) {
x = read(), y = read();
int fx = father(x), fy = father(y);
if (fx != fy) {
cnt++;
fath[fx] = fy;
}
}
n--;
if (cnt == n) puts("0");
else cout << n - cnt << "\n";
}
T4
好妙
首先你可以写出一个人人都会的 \(n^2\) dp式子,长这个样子。
\[dp_i = \max (dp_i, dp_j + 1)
\]
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i - 1; j++)
if (abs(a[i] - a[j]) <= k) dp[i] = max(dp[i], dp[j] + 1);
上边这个需要 \(n^2\) 解决,考虑将内层循环优化掉。
考虑线段树维护a值域,线段树中存 dp 值,我们可以每次找 \([a_i-k, a_i+k]\) 区间内的最大值,然后将这个最大值插入 \(a_i\) 中,同时我们记录当前的 dp 值。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define lson rt << 1
#define rson rt << 1 | 1
#define N 300010
#define M 1010
using namespace std;
int n, k, a[N], dp[N];
struct node {
int sum;
}tree[N << 2];
int read() {
int s = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void push_up(int rt) {
tree[rt].sum = max(tree[lson].sum, tree[rson].sum);
}
void build(int rt, int l, int r) {
tree[rt].sum = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
push_up(rt);
}
void change(int rt, int c, int l, int r, int pos) {
if (l == r) {
tree[rt].sum = c;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) change(lson, c, l, mid, pos);
else change(rson, c, mid + 1, r, pos);
push_up(rt);
}
int query(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R) return tree[rt].sum;
int mid = (l + r) >> 1, ans = 0;
if (L <= mid) ans = max(ans, query(lson, l, mid, L, R));
if (R > mid) ans = max(ans, query(rson, mid + 1, r, L, R));
return ans;
}
int main() {
n = read(), k = read();
int m = 0;
for (int i = 1; i <= n; i++) a[i] = read(), m = max(a[i] + 1, m);
build(1, 1, m);
for (int i = 1; i <= n; i++) {
dp[i] = query(1, 1, m, max(a[i] - k, 1), min(a[i] + k, m)) + 1;
change(1, dp[i], 1, m, a[i]);
}
int ans = 0;
for (int i = 1; i <= n; i++) ans = max(ans, dp[i]);
cout << ans << "\n";
}
T5
可以线段树解决
上传的时候就是
void push_up(int rt) {
tree[rt].sum = ((tree[lson].sum * q_pow(10, tree[rson].len)) % mod + tree[rson].sum) % mod;
}
应该很好理解。
我们发现 \(77777777 = (10^8 - 1) \times \frac{7}{9}\)
然后我们可以根据这个东西搞一搞懒标记下放和修改操作。
预处理 9 在 \(\text{mod}\) 998244353 的逆元即可。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define lson rt << 1
#define rson rt << 1 | 1
#define N 200010
#define M 1010
using namespace std;
const int mod = 998244353;
const int inv = 443664157;
int n, m;
struct node {
ll sum, len, lazy;
}tree[N << 2];
int read() {
int s = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
ll q_pow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1) ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ans;
}
void push_up(int rt) {
tree[rt].sum = ((tree[lson].sum * q_pow(10, tree[rson].len)) % mod + tree[rson].sum) % mod;
}
void build(int rt, int l, int r) {
tree[rt].lazy = 0, tree[rt].len = (r - l + 1) * 1ll;
if (l == r) {
tree[rt].sum = 1ll;
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
push_up(rt);
}
void push_down(int rt) {
if (!tree[rt].lazy) return;
tree[lson].sum = ((q_pow(10, tree[lson].len) - 1ll + mod) % mod * tree[rt].lazy) % mod;
tree[lson].sum = (tree[lson].sum * inv) % mod;
tree[rson].sum = ((q_pow(10, tree[rson].len) - 1ll + mod) % mod * tree[rt].lazy) % mod;
tree[rson].sum = (tree[rson].sum * inv) % mod;
tree[lson].lazy = tree[rt].lazy;
tree[rson].lazy = tree[rt].lazy;
tree[rt].lazy = 0;
}
void change(int rt, ll col, int l, int r, int L, int R) {
if (L <= l && r <= R) {
tree[rt].sum = ((q_pow(10, tree[rt].len) - 1ll + mod) % mod * col) % mod;
tree[rt].sum = (tree[rt].sum * inv) % mod;
tree[rt].lazy = col;
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if (L <= mid) change(lson, col, l, mid, L, R);
if (R > mid) change(rson, col, mid + 1, r, L, R);
push_up(rt);
}
int main() {
n = read(), m = read();
build(1, 1, n);
for (int i = 1; i <= m; i++) {
ll l = read(), r = read(), c = read();
change(1, c, 1, n, l, r);
printf("%lld\n", tree[1].sum);
}
return 0;
}

浙公网安备 33010602011771号