NOIP前板子复习
再不复习板子我就是 [ 数据删除 ]
高精度
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int power = 4, base = 10000; //修改压位
char a[233333], b[233333];
//初始化
struct HP
{
int len, p[2333];
HP() { len = 0; memset(p, 0, sizeof(p)); }
HP(char *s)
{
len = (strlen(s) + power - 1) / power;
memset(p, 0, sizeof(p));
for(int i = 0, t = 0, w; i < strlen(s); i++, w *= 10)
{
if(i % power == 0) t++, w = 1;
p[t] += (s[i] - '0') * w;
}
}
void rev() { reverse(p + 1, p + len + 1); }
void add(int k) { if(len || k) p[++len] = k; }
void print()
{
printf("%d", p[len]);
for(int i = len - 1; i > 0; i--) printf("%0*d", power, p[i]);
printf("\n");
}
} p, q, ans;
//重载运算符
bool operator < (const HP &a, const HP &b)
{
if(a.len < b.len) return true;
if(a.len > b.len) return false;
for(int i = a.len; i > 0; i--)
if(a.p[i] != b.p[i]) return a.p[i] < b.p[i];
return false;
}
HP operator + (const HP &a, const HP &b)
{
HP c = a;
c.len = max(a.len, b.len);
for(int i = 1; i <= c.len; i++)
{
c.p[i] += b.p[i];
c.p[i + 1] += c.p[i] / base;
c.p[i] %= base;
}
if(c.p[c.len + 1]) c.len++;
return c;
}
HP operator - (const HP &a, const HP &b)
{
HP c = a;
for(int i = 1; i <= c.len; i++)
{
c.p[i] -= b.p[i];
if(c.p[i] < 0) c.p[i] += base, c.p[i + 1]--;
}
while(c.len && !c.p[c.len]) c.len--;
return c;
}
HP operator * (const HP &a, const HP &b)
{
HP c;
c.len = a.len + b.len - 1;
for(int i = 1; i <= a.len; i++)
for(int j = 1; j <= b.len; j++)
{
c.p[i + j - 1] += a.p[i] * b.p[j];
c.p[i + j] += c.p[i + j - 1] / base;
c.p[i + j - 1] %= base;
}
while(c.p[c.len + 1]) c.len++;
return c;
}
HP operator / (const HP &a, const HP &b)
{
HP u, v;
u.len = a.len;
for(int i = a.len; i > 0; i--)
{
v.add(a.p[i]), v.rev();
while(!(v < b)) v = v - b, u.p[i]++;
v.rev();
}
while(u.len && !u.p[u.len]) u.len--;
return u;
}
HP operator % (const HP &a, const HP &b) { return a - (a / b) * b; }
//以下是洛谷P1932主函数
int main()
{
scanf("%s", &a), scanf("%s", &b);
reverse(a, a + strlen(a)), reverse(b, b + strlen(b));
p = HP(a), q = HP(b);
ans = p + q; ans.print();
if(p < q) { printf("-"); ans = q - p; }
else ans = p - q;
ans.print();
ans = p * q; ans.print();
ans = p / q; ans.print();
ans = p % q; ans.print();
return 0;
}
二分查找
//估计没有人写这么骚气的二分查找吧...
int l = left_limit, r = right_limit;
while(l + 1 < r)
{
int mid = (l + r) >> 1;
if(check(mid)) l = mid; //or r = mid;
else r = mid; //or l = mid;
}
st 1:
if(check(l)) ans = l;
else ans = r;
st 2:
if(check(r)) ans = r;
else ans = l;
tarjan 缩点
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 10006, M = 100006;
struct edge
{
int nxt, to;
} e[M];
int n, m, ans = 0, cnt = 0, id = 0, top = 0, col = 0;
int a[N], head[N], low[N], dfn[N], c[N], st[N], s[M], t[M];
int val[N], f[N], du[N], vis[N];
inline int read()
{
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - 48; c = getchar(); }
return x * f;
}
void add(int x, int y)
{
e[++cnt] = (edge) { head[x], y };
head[x] = cnt;
}
void dfs(int x) //板子部分
{
dfn[x] = low[x] = ++id;
st[++top] = x;
vis[x] = 1;
for(int i = head[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if(!dfn[v]) { dfs(v); low[x] = min(low[x], low[v]); }
else if(vis[v]) low[x] = min(low[x], dfn[v]);
}
if(dfn[x] == low[x])
{
col++;
st[top + 1] = -1;
while(st[top + 1] != x)
{
c[st[top]] = col;
vis[st[top--]] = 0;
}
}
}
void top_sort()
{
int m = col;
for(int i = 1; i <= col; i++) f[i] = val[i];
queue <int> q;
for(int i = 1; i <= col; i++) if(!du[i]) q.push(i);
while(!q.empty())
{
int a = q.front();
q.pop();
for(int i = head[a]; i; i = e[i].nxt)
{
int v = e[i].to;
du[v]--;
f[v] = max(f[v], f[a] + val[v]);
if(!du[v]) q.push(v);
}
}
for(int i = 1; i <= col; i++) ans = max(ans, f[i]);
}
int main()
{
n = read(), m = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= m; i++)
{
s[i] = read(), t[i] = read();
add(s[i], t[i]);
}
memset(dfn, 0, sizeof(dfn));
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++) if(!dfn[i]) dfs(i);
memset(head, 0, sizeof(head));
memset(val, 0, sizeof(val));
cnt = 0;
for(int i = 1; i <= m; i++)
if(c[s[i]] != c[t[i]])
{
add(c[s[i]], c[t[i]]);
du[c[t[i]]]++;
}
for(int i = 1; i <= n; i++) val[c[i]] += a[i];
top_sort();
printf("%d", ans);
return 0;
}
二分图最大匹配
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int n, m, E, ans = 0, e[N][N], girl[N], use[N];
bool find(int x)
{
for(int j = 1; j <= m; j++)
if(e[x][j] == 1 && use[j] == 0)
{
use[j] = 1;
if(girl[j] == 0 || find(girl[j]))
{
girl[j] = x;
return true;
}
}
return false;
}
int main()
{
scanf("%d%d%d", &n, &m, &E);
memset(e, 0, sizeof(e));
memset(girl, 0, sizeof(girl));
for(int u, v, i = 1; i <= E; i++)
{
scanf("%d%d", &u, &v);
if(u < 1 || u > n || v < 1 || v > m) continue;
e[u][v] = 1;
}
for(int i = 1; i <= n; i++)
{
memset(use, 0, sizeof(use));
ans += find(i);
}
printf("%d", ans);
return 0;
}
状压 dp 枚举子集
for(int i = S; i; i = ((i - 1) & S))
Kruskal 最小生成树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const int N = 2333333;
LL n, m, ans = 0, f[N];
struct edge { LL u, v, w; } e[N];
bool cmp(edge a, edge b) { return a.w < b.w; }
LL find(LL x) { return x == f[x] ? x : f[x] = find(f[x]); }
int main()
{
scanf("%lld%lld", &n, &m);
for(int i = 1; i <= n; i++) f[i] = i;
for(int i = 1; i <= m; i++)
scanf("%lld%lld%lld", &e[i].u, &e[i].v, &e[i].w);
sort(e + 1, e + m + 1, cmp);
for(int i = 1; i <= m; i++)
if(find(e[i].u) != find(e[i].v))
{
f[find(e[i].u)] = find(e[i].v);
ans += e[i].w;
}
printf("%lld", ans);
return 0;
}
倍增求 LCA
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 500010;
struct edge { int nxt, to; } e[N << 1];
int n, m, s, cnt = 0, u, v, f[N][23], deep[N], head[N];
void dfs(int x, int fa)
{
deep[x] = deep[fa] + 1;
f[x][0] = x, f[x][1] = fa;
for(int i = 2; i <= 20; i++)
f[x][i] = f[f[x][i - 1]][i - 1];
for(int i = head[x]; i; i = e[i].nxt)
if(e[i].to != fa) dfs(e[i].to, x);
}
int LCA(int x, int y)
{
if(deep[x] < deep[y]) swap(x, y);
for(int i = 20; i >= 0; i--)
if(deep[f[x][i]] >= deep[y]) x = f[x][i];
if(x == y) return x;
for(int i = 20; i >= 0; i--)
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][1];
}
void add(int x, int y) { e[++cnt] = (edge) { head[x], y }; head[x] = cnt; }
int main()
{
scanf("%d%d%d", &n, &m, &s);
memset(head, 0, sizeof(head));
for(int i = 1; i < n; i++)
scanf("%d%d", &u, &v), add(u, v), add(v, u);
deep[0] = 0, dfs(s, 0);
while(m--) scanf("%d%d", &u, &v), printf("%d\n", LCA(u, v));
return 0;
}
spfa
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define LL long long
using namespace std;
const int N = 2333333;
struct edge { LL nxt, to, w; } e[N << 1];
LL n, m, s, cnt = 0, head[N], dis[N], vis[N];
void add(LL x, LL y, LL w)
{
e[++cnt] = (edge) { head[x], y, w };
head[x] = cnt;
}
void spfa()
{
for(int i = 0; i <= n + 1; i++) dis[i] = (1 << 31) - 1;
memset(vis, 0, sizeof(vis));
queue <LL> q;
q.push(s);
vis[s] = 1, dis[s] = 0;
while(!q.empty())
{
LL a = q.front();
q.pop();
vis[a] = 0;
for(int i = head[a]; i; i = e[i].nxt)
{
LL v = e[i].to;
if(dis[v] > dis[a] + e[i].w)
{
dis[v] = dis[a] + e[i].w;
if(!vis[v]) { vis[v] = 1; q.push(v); }
}
}
}
}
int main()
{
scanf("%lld%lld%lld", &n, &m, &s);
for(LL u, v, w, i = 1; i <= m; i++)
{
scanf("%lld%lld%lld", &u, &v, &w);
add(u, v, w);
}
spfa();
for(int i = 1; i <= n; i++) printf("%lld ", dis[i]);
return 0;
}
dijkstra + 堆优化
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define LL long long
using namespace std;
const int N = 2333333;
struct edge { LL nxt, to, w; } e[N];
LL n, m, s, cnt = 0, vis[N], dis[N], head[N];
void add(LL x, LL y, LL w)
{
e[++cnt] = (edge) { head[x], y, w };
head[x] = cnt;
}
struct node
{
LL x, dis;
friend bool operator < (node x, node y) { return x.dis > y.dis; }
};
void dijkstra()
{
priority_queue <node> q;
memset(dis, 0x7f7f7f, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[s] = 0, q.push((node) { s, 0 });
while(!q.empty())
{
LL a = q.top().x;
q.pop();
if(vis[a]) continue;
vis[a] = 1;
for(int i = head[a]; i; i = e[i].nxt)
{
LL v = e[i].to;
if(dis[v] > dis[a] + e[i].w)
{
dis[v] = dis[a] + e[i].w;
if(!vis[v]) q.push((node) { v, dis[v] });
}
}
}
}
int main()
{
scanf("%lld%lld%lld", &n, &m, &s);
memset(head, 0, sizeof(head));
for(LL u, v, w, i = 1; i <= m; i++)
scanf("%lld%lld%lld", &u, &v, &w), add(u, v, w);
dijkstra();
for(int i = 1; i <= n; i++) printf("%lld ", dis[i]);
return 0;
}
并查集
用时 \(\mathrm{2 \space min}\)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2333333;
int n, m, f[N];
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) f[i] = i;
for(int x, y, z, i = 1; i <= m; i++)
{
scanf("%d%d%d", &z, &x, &y);
if(z == 1) f[find(x)] = find(y);
else
{
if(find(x) == find(y)) printf("Y\n");
else printf("N\n");
}
}
return 0;
}
树状数组
用时 \(5 \space \mathrm{min}\)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define lowbit(x) (x & (-x))
using namespace std;
const int N = 2333333;
LL n, m, t[N];
void add(LL x, LL k) { while(x <= n) t[x] += k, x += lowbit(x); }
LL query(LL x)
{
LL res = 0;
while(x) res += t[x], x -= lowbit(x);
return res;
}
int main()
{
scanf("%lld%lld", &n, &m);
for(LL a, i = 1; i <= n; i++) scanf("%d", &a), add(i, a);
for(LL opt, x, y, i = 1; i <= m; i++)
{
scanf("%lld%lld%lld", &opt, &x, &y);
if(opt == 1) add(x, y);
else printf("%lld\n", query(y) - query(x - 1));
}
return 0;
}
线段树 单点修改 + 区间查询
用时 \(7 \space \mathrm{min}\)
#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
const LL N = 666666;
LL n, m, a[N], sum[N << 2];
struct Segment_Tree
{
void push_up(LL x) { sum[x] = sum[x << 1] + sum[x << 1 | 1]; }
void build(LL x, LL l, LL r)
{
if(l == r)
{
sum[x] = a[l];
return ;
}
LL mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
push_up(x);
}
void update(LL x, LL l, LL r, LL std, LL k)
{
if(r < std || l > std) return ;
if(l == std && r == std)
{
sum[x] += k;
return ;
}
LL mid = (l + r) >> 1;
update(x << 1, l, mid, std, k);
update(x << 1 | 1, mid + 1, r, std, k);
push_up(x);
}
LL query(LL x, LL l, LL r, LL stdl, LL stdr)
{
if(l > stdr || r < stdl) return 0;
if(stdl <= l && stdr >= r) return sum[x];
LL mid = (l + r) >> 1;
return query(x << 1, l, mid, stdl, stdr) +
query(x << 1 | 1, mid + 1, r, stdl, stdr);
push_up(x);
}
} tree;
int main()
{
scanf("%lld%lld", &n, &m);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
tree.build(1, 1, n);
for(LL opt, x, y, i = 1; i <= m; i++)
{
scanf("%lld%lld%lld", &opt, &x, &y);
if(opt == 1) tree.update(1, 1, n, x, y);
else printf("%lld\n", tree.query(1, 1, n, x, y));
}
return 0;
}
线段树 区间修改 + 单点查询
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2333333;
int n, m, a[N], tag[N], sum[N];
struct Segment_Tree
{
void push_up(int x) { sum[x] = sum[x << 1] + sum[x << 1 | 1]; }
void push_down(int x, int l, int r)
{
int mid = (l + r) >> 1;
tag[x << 1] += tag[x];
tag[x << 1 | 1] += tag[x];
sum[x << 1] += tag[x] * (mid - l + 1);
sum[x << 1 | 1] += tag[x] * (r - mid);
tag[x] = 0;
}
void build(int x, int l, int r)
{
if(l == r)
{
sum[x] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
push_up(x);
}
void update(int x, int l, int r, int stdl, int stdr, int k)
{
if(l > stdr || r < stdl) return ;
if(stdl <= l && stdr >= r)
{
tag[x] += k, sum[x] += k * (r - l + 1);
push_down(x, l, r);
return ;
}
int mid = (l + r) >> 1;
push_down(x, l, r);
update(x << 1, l, mid, stdl, stdr, k);
update(x << 1 | 1, mid + 1, r, stdl, stdr, k);
push_up(x);
}
int query(int x, int l, int r, int std)
{
if(l > std || r < std) return 0;
if(l == std && r == std) return sum[x];
int mid = (l + r) >> 1;
push_down(x, l, r);
return query(x << 1, l, mid, std) +
query(x << 1 | 1, mid + 1, r, std);
push_up(x);
}
} tree;
int main()
{
scanf("%d%d", &n, &m);
memset(tag, 0, sizeof(tag));
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
tree.build(1, 1, n);
for(int opt, x, y, k, i = 1; i <= m; i++)
{
scanf("%d", &opt);
if(opt == 1)
{
scanf("%d%d%d", &x, &y, &k);
tree.update(1, 1, n, x, y, k);
}
else
{
scanf("%d", &x);
printf("%d\n", tree.query(1, 1, n, x));
}
}
return 0;
}
线段树 区间修改 + 区间查询
用时 \(9 \space \mathrm{min}\)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const LL N = 100100;
LL n, m, a[N], sum[N << 2], tag[N << 2];
struct Segment_Tree
{
void push_up(LL x) { sum[x] = sum[x << 1] + sum[x << 1 | 1]; }
void push_down(LL x, LL l, LL r)
{
LL mid = (l + r) >> 1;
if(!tag[x]) return ;
tag[x << 1] += tag[x], tag[x << 1 | 1] += tag[x];
sum[x << 1] += (mid - l + 1) * tag[x];
sum[x << 1 | 1] += (r - mid) * tag[x];
tag[x] = 0;
}
void build(LL x, LL l, LL r)
{
if(l == r)
{
sum[x] = a[l];
return ;
}
LL mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
push_down(x, l, r), push_up(x);
}
void update(LL x, LL l, LL r, LL stdl, LL stdr, LL k)
{
if(l > stdr || r < stdl) return ;
if(stdl <= l && stdr >= r)
{
tag[x] += k;
sum[x] += (r - l + 1) * k;
push_down(x, l, r);
return ;
}
LL mid = (l + r) >> 1;
push_down(x, l, r);
update(x << 1, l, mid, stdl, stdr, k);
update(x << 1 | 1, mid + 1, r, stdl, stdr, k);
push_down(x, l, r), push_up(x);
}
LL query(LL x, LL l, LL r, LL stdl, LL stdr)
{
if(l > stdr || r < stdl) return 0;
if(stdl <= l && stdr >= r) return sum[x];
LL mid = (l + r) >> 1;
push_down(x, l, r);
return query(x << 1, l, mid, stdl, stdr) +
query(x << 1 | 1, mid + 1, r, stdl, stdr);
push_up(x);
}
} tree;
int main()
{
scanf("%lld%lld", &n, &m);
for(LL i = 1; i <= n; i++) scanf("%lld", &a[i]);
tree.build(1, 1, n);
for(LL opt, x, y, k, i = 1; i <= m; i++)
{
scanf("%lld", &opt);
if(opt == 1)
{
scanf("%lld%lld%lld", &x, &y, &k);
tree.update(1, 1, n, x, y, k);
}
else
{
scanf("%lld%lld", &x, &y);
printf("%lld\n", tree.query(1, 1, n, x, y));
}
}
return 0;
}
线段树 区间乘法 + 区间加法
用时 \(114514 \space \mathrm{min}\)
#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
const int N = 2333333;
LL n, m, p, a[N], sum[N], mul[N], add[N];
struct Segment_Tree
{
void push_up(LL x) { sum[x] = (sum[x << 1] + sum[x << 1 | 1] + p) % p; }
void push_down(LL x, LL l, LL r)
{
LL mid = (l + r) >> 1;
mul[x << 1] = (mul[x << 1] * mul[x] + p) % p;
mul[x << 1 | 1] = (mul[x << 1 | 1] * mul[x] + p) % p;
add[x << 1] = (add[x << 1] * mul[x] + add[x] + p) % p;
add[x << 1 | 1] = (add[x << 1 | 1] * mul[x] + add[x] + p) % p;
sum[x << 1] = (sum[x << 1] * mul[x] + add[x] * (mid - l + 1) + p) % p;
sum[x << 1 | 1] = (sum[x << 1 | 1] * mul[x] + add[x] * (r - mid) + p) % p;
mul[x] = 1, add[x] = 0;
}
void build(LL x, LL l, LL r)
{
add[x] = 0, mul[x] = 1;
if(l == r)
{
sum[x] = (a[l] + p) % p;
return ;
}
LL mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
push_up(x);
}
void update1(LL x, LL l, LL r, LL stdl, LL stdr, LL k)
{
if(l > stdr || r < stdl) return ;
if(stdl <= l && stdr >= r)
{
mul[x] = (mul[x] * k + p) % p;
add[x] = (add[x] * k + p) % p;
sum[x] = (sum[x] * k + p) % p;
push_down(x, l, r);
return ;
}
LL mid = (l + r) >> 1;
push_down(x, l, r);
update1(x << 1, l, mid, stdl, stdr, k);
update1(x << 1 | 1, mid + 1, r, stdl, stdr, k);
push_down(x, l, r), push_up(x);
}
void update2(LL x, LL l, LL r, LL stdl, LL stdr, LL k)
{
if(l > stdr || r < stdl) return ;
if(stdl <= l && stdr >= r)
{
add[x] = (add[x] + k + p) % p;
sum[x] = (sum[x] + k * (r - l + 1) + p) % p;
push_down(x, l, r);
return ;
}
LL mid = (l + r) >> 1;
push_down(x, l, r);
update2(x << 1, l, mid, stdl, stdr, k);
update2(x << 1 | 1, mid + 1, r, stdl, stdr, k);
push_down(x, l, r), push_up(x);
}
LL query(LL x, LL l, LL r, LL stdl, LL stdr)
{
if(l > stdr || r < stdl) return 0;
if(stdl <= l && stdr >= r) return (sum[x] + p) % p;
LL mid = (l + r) >> 1;
push_down(x, l, r);
return (query(x << 1, l, mid, stdl, stdr) +
query(x << 1 | 1, mid + 1, r, stdl, stdr) + p) % p;
}
} tree;
int main()
{
scanf("%lld%lld%lld", &n, &m, &p);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
tree.build(1, 1, n);
for(LL opt, x, y, k, i = 1; i <= m; i++)
{
scanf("%lld", &opt);
if(opt == 1)
{
scanf("%lld%lld%lld", &x, &y, &k);
tree.update1(1, 1, n, x, y, k);
}
else if(opt == 2)
{
scanf("%lld%lld%lld", &x, &y, &k);
tree.update2(1, 1, n, x, y, k);
}
else
{
scanf("%lld%lld", &x, &y);
printf("%lld\n", tree.query(1, 1, n, x, y));
}
}
return 0;
}
快速幂
int poww(int b, int p, int k)
{
int ans = 1;
while(p)
{
if(p & 1) ans = (ans * b) % k;
b = (b * b) % k;
p >>= 1;
}
return ans;
}
单调队列
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 2333333;
long long n, k, head = 1, tail = 0, a[N], q[N];
int main()
{
scanf("%lld%lld", &n, &k);
memset(q, 0, sizeof(q));
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for(int i = 1; i <= n; i++)
{
while(head <= tail && q[head] <= i - k) head++;
while(head <= tail && a[q[tail]] >= a[i]) tail--;
q[++tail] = i;
if(i >= k) printf("%lld ", a[q[head]]);
}
printf("\n");
head = 1, tail = 0, memset(q, 0, sizeof(q));
for(int i = 1; i <= n; i++)
{
while(head <= tail && q[head] <= i - k) head++;
while(head <= tail && a[q[tail]] <= a[i]) tail--;
q[++tail] = i;
if(i >= k) printf("%lld ", a[q[head]]);
}
return 0;
}
01 背包
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 23333;
int t, n, w[N], v[N], f[N];
int main()
{
scanf("%d%d", &t, &n);
memset(f, 0, sizeof(f));
for(int i = 1; i <= n; i++) scanf("%d%d", &w[i], &v[i]);
for(int i = 1; i <= n; i++)
for(int j = t; j >= w[i]; j--)
f[j] = max(f[j], f[j - w[i]] + v[i]);
printf("%d", f[t]);
return 0;
}