暴力。 Θ ( n m s ) \Theta(nms) Θ(nms)
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG(FMT...) fprintf(stderr, FMT)
using namespace std;
const int N = 110, S = 110, M = 20010;
int n, m, s;
int a[S][N];
int cur[S];
int dp[M];
int main() {
scanf("%d%d%d", &s, &n, &m);
for (int i = 1; i <= s; ++i)
for (int j = 1; j <= n; ++j)
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= s; ++j)
cur[j] = a[j][i] * 2 + 1;
sort(cur + 1, cur + s + 1);
for (int j = m; j; --j)
for (int k = 1; cur[k] <= j && k <= s; ++k)
dp[j] = max(dp[j], dp[j - cur[k]] + k * i);
}
printf("%d\n", dp[m]);
return 0;
}
消元。 Θ ( n ) \Theta(n) Θ(n)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG(FMT...) fprintf(stderr, FMT)
using namespace std;
typedef long long ll;
const int N = 500010, P = 1000000007;
int n;
int mat[N * 2][5], v[N * 2];
int norm(int x) { return x >= P ? x - P : x; }
void exGcd(int a, int b, int& x, int& y) {
if (!b) {
x = 1;
y = 0;
return;
}
exGcd(b, a % b, y, x);
y -= a / b * x;
}
int inv(int a) {
int x, y;
exGcd(a, P, x, y);
return norm(x + P);
}
void elim(int n) {
for (int i = 0; i < n; ++i) {
int in = inv(mat[i][2]);
for (int j = 2; j < 5; ++j)
mat[i][j] = mat[i][j] * (ll)in % P;
v[i] = v[i] * (ll)in % P;
for (int j = i + 1; j < n && j <= i + 2; ++j) {
v[j] = (v[j] + (P - mat[j][2 - (j - i)]) * (ll)v[i]) % P;
for (int k = 3; k < 5; ++k)
mat[j][k - (j - i)] = (mat[j][k - (j - i)] + (P - mat[j][2 - (j - i)]) * (ll)mat[i][k]) % P;
mat[j][2 - (j - i)] = 0;
}
}
}
int main() {
scanf("%d", &n);
int I100 = inv(100);
for (int i = 0; i <= n * 2; ++i)
mat[i][2] = 1;
for (int i = 0; i < n; ++i) {
int a, b;
scanf("%d%d", &a, &b);
mat[(i + 1) << 1][0] = mat[i << 1 | 1][4] = (P - a) * (ll)I100 % P;
mat[i << 1 | 1][1] = mat[(i + 1) << 1][3] = (P - b) * (ll)I100 % P;
}
v[0] = 1;
elim(n * 2 + 1);
printf("%d\n", v[n * 2]);
return 0;
}
注意到把 i i i 在数轴上的 [ i − c n t ( i ) , i ] [i-cnt(i), i] [i−cnt(i),i] 线段涂色,在 [ 0 , n ] [0, n] [0,n] 上没被染色的部分就是答案,用线段树打 Tag 维护即可。 Θ ( n log n ) \Theta(n \log n) Θ(nlogn)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG(FMT...) fprintf(stderr, FMT)
using namespace std;
struct Node {
int l, r;
Node *ls, *rs;
int tag, s;
void upd() {
if (tag)
s = 0;
else if (l == r)
s = 1;
else
s = ls->s + rs->s;
}
void ch(int l, int r, int x) {
if (this->l == l && this->r == r) {
tag += x;
upd();
return;
}
if (r <= ls->r)
ls->ch(l, r, x);
else if (l >= rs->l)
rs->ch(l, r, x);
else {
ls->ch(l, ls->r, x);
rs->ch(rs->l, r, x);
}
upd();
}
int qry(int l, int r) {
if (tag)
return 0;
if (this->l == l && this->r == r)
return s;
if (r <= ls->r)
return ls->qry(l, r);
if (l >= rs->l)
return rs->qry(l, r);
return ls->qry(l, ls->r) + rs->qry(rs->l, r);
}
};
const int N = 150010;
int n, lazy;
int a[N], cnt[N * 4];
Node* seg;
Node* build(int l, int r) {
static Node pool[N * 8], *ptop = pool;
Node* p = ptop++;
p->l = l;
p->r = r;
p->s = r - l + 1;
if (l == r)
return p;
int mid = (l + r) >> 1;
p->ls = build(l, mid);
p->rs = build(mid + 1, r);
return p;
}
void inc(int k) {
if (k > lazy + n) {
++cnt[k];
} else {
if (cnt[k])
seg->ch(k - cnt[k] + 1, k, -1);
++cnt[k];
seg->ch(k - cnt[k] + 1, k, 1);
}
}
void dec(int k) {
if (k > lazy + n) {
--cnt[k];
} else {
seg->ch(k - cnt[k] + 1, k, -1);
if (--cnt[k])
seg->ch(k - cnt[k] + 1, k, 1);
}
}
void modify(int k, int x) {
if (a[k] == x + lazy)
return;
if (a[k])
dec(a[k]);
a[k] = x + lazy;
inc(x + lazy);
}
int main() {
int m;
scanf("%d%d", &n, &m);
seg = build(1, (n + m) * 2);
lazy = m + n;
for (int i = 1; i <= n; ++i) {
int x;
scanf("%d", &x);
modify(i, x);
}
while (m--) {
int p, x;
scanf("%d%d", &p, &x);
if (p == 0) {
if (x == 1) {
--lazy;
if (cnt[lazy + n + 1])
seg->ch(lazy + n + 1 - cnt[lazy + n + 1] + 1, lazy + n + 1, -1);
} else {
++lazy;
if (cnt[lazy + n])
seg->ch(lazy + n - cnt[lazy + n] + 1, lazy + n, 1);
}
} else
modify(p, x);
printf("%d\n", seg->qry(lazy + 1, lazy + n));
}
return 0;
}