20240819总结
总分 \(400 pts\),得分为 \(40 pts\),鉴定为史上最菜的 Oier。
card
每次修改相当于添加一个数和删除一个数,考虑添加一个数,如果覆盖的区间没有其他的,则自己不用修改,如果有,就需要修改,如果覆盖区间超过了自己数值,则超出的部分都需要修改。
#include<iostream>
using namespace std;
inline int read(){register int x = 0, f = 1;register char c = getchar();while (c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}while (c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f;}
inline void write(int x){if (x < 0) putchar('-'), x = -x;if (x > 9) write(x / 10);putchar(x % 10 + '0');}
const int N = 2e5 + 10;
int n, m, ans;
int a[N], cnt[N], tot[N];
void add(int x){
cnt[x]++;
if (x - cnt[x] + 1 >= 1){
if (!tot[x - cnt[x] + 1]) ans++;
tot[x - cnt[x] + 1]++;
}
}
void del(int x){
if (x - cnt[x] + 1 >= 1){
tot[x - cnt[x] + 1]--;
if (!tot[x - cnt[x] + 1]) ans--;
}
cnt[x]--;
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; i++) a[i] = read(), add(a[i]);
for (int i = 1; i <= m; i++){
int x = read(), y = read();
del(a[x]);
add(a[x] = y);
cout << n - ans << '\n';
}
return 0;
}
sort
可以发现性质,奇数位上的和模 \(11\),等于偶数位上的和模 \(11\),设 \(dp_{i,j}\) 表示用 \(i\) 个数,凑出余 \(j\) 的方案数个数。
在高位从 \(9\) 枚举到 \(0\),看是否能填入,如果能,就填,如何判断?将 \(dp\) 退掉 \(9\) 之后再看是否能满足上面结论。
#include<iostream>
#include<cstring>
using namespace std;
inline int read(){register int x = 0, f = 1;register char c = getchar();while (c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}while (c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f;}
inline void write(int x){if (x < 0) putchar('-'), x = -x;if (x > 9) write(x / 10);putchar(x % 10 + '0');}
const int N = 1e3 + 10;
char c[N];
int n, cnt, sum;
int f[N][12], tot[12];
void add(int x){
for (int i = cnt; i >= 0; i--){
for (int j = 0; j <= 10; j++){
f[i + 1][(j + x) % 11] += f[i][j];
}
}
tot[x]++, cnt++;
}
void del(int x){
for (int i = 0; i <= cnt; i++){
for (int j = 0; j <= 10; j++){
f[i + 1][(j + x) % 11] -= f[i][j];
}
}
tot[x]--, cnt--;
}
int main(){
cin >> c + 1;
n = strlen(c + 1);
f[0][0] = 1;
for (int i = 1; i <= n; i++) add(c[i] - '0'), sum += c[i] - '0';
int s = sum * 6 % 11, fir, sec, now1 = s, now2 = s;
for (int i = 1; i <= n; i++){
if (i & 1) fir = n / 2 - i / 2, sec = now1;
else fir = (n + 1) / 2 - (i + 1) / 2, sec = now2;
int x = 9;
while (1){
if (!tot[x]){
x--;
continue;
}
del(x);
if (f[fir][sec]) break;
add(x);
x--;
}
if (i & 1) now2 = (now2 - x + 11) % 11;
else now1 = (now1 - x + 11) % 11;
cout << x;
}
return 0;
}
offsheet
看到此题,第一眼费用流,但是暴力建边时间复杂度会爆炸,由于要求 \(|x_1-x_2|+|y_1-y_2|\) 的最大值,则用四个点连边,分别代表 \(x_1+x_2\),\(x_1-x_2\),\(-x_1+x_2\),\(-x_1-x_2\),这样就能跑费用流了。
#include<iostream>
#include<queue>
#define int long long
#define INF 1e17
using namespace std;
inline int read(){register int x = 0, f = 1;register char c = getchar();while (c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}while (c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f;}
inline void write(int x){if (x < 0) putchar('-'), x = -x;if (x > 9) write(x / 10);putchar(x % 10 + '0');}
const int N = 5e4 + 10, M = 1e5 + 10;
int n, s, t, ans;
struct edge{
int v, w, c, nxt;
}e[M << 1];
int head[N], cnt = 1;
void add_edge(int u, int v, int w, int c){
e[++cnt] = (edge){v, w, c, head[u]};
head[u] = cnt;
}
void add(int u, int v, int w, int c){
add_edge(u, v, w, c);
add_edge(v, u, 0, -c);
}
int dis[N], cur[N];
bool vis[N], flag[N];
queue<int> q;
bool spfa(){
for (int i = s; i <= t; i++) dis[i] = -INF, vis[i] = 0;
dis[s] = 0, vis[s] = 1;
q.push(s);
while (!q.empty()){
int u = q.front();
vis[u] = 0;
q.pop();
for (int i = head[u]; i; i = e[i].nxt){
int v = e[i].v;
if (e[i].w > 0 && dis[v] < dis[u] + e[i].c){
dis[v] = dis[u] + e[i].c;
if (!vis[v]) vis[v] = 1, q.push(v);
}
}
}
return dis[t] != -INF;
}
int dfs(int u, int sum){
if (u == t) return sum;
int res = 0;
flag[u] = 1;
for (int i = cur[u]; i; i = e[i].nxt){
cur[u] = i;
int v = e[i].v;
if (e[i].w > 0 && dis[v] == dis[u] + e[i].c && !flag[v]){
int s = dfs(v, min(sum, e[i].w));
e[i].w -= s, e[i ^ 1].w += s;
res += s, sum -= s, ans += s * e[i].c;
if (sum == 0) return res;
}
}
flag[u] = 0;
return res;
}
void Dinic(){
while (spfa()){
for (int i = s; i <= t; i++) cur[i] = head[i], flag[i] = 0;
dfs(s, INF);
}
}
signed main(){
n = read();
s = 0, t = 2 * n + 5;
for (int i = 1; i <= n; i++){
int x = read(), y = read(), c = read();
add(s, i, c, 0);
add(i, 2 * n + 1, c, x + y);
add(i, 2 * n + 2, c, x - y);
add(i, 2 * n + 3, c, -x + y);
add(i, 2 * n + 4, c, -x - y);
}
for (int i = 1; i <= n; i++){
int x = read(), y = read(), c = read();
add(i + n, t, c, 0);
add(2 * n + 1, i + n, c, -x - y);
add(2 * n + 2, i + n, c, -x + y);
add(2 * n + 3, i + n, c, x - y);
add(2 * n + 4, i + n, c, x + y);
}
Dinic();
cout << ans;
return 0;
}

浙公网安备 33010602011771号