CSP 前模板记录(黄题篇)
快要 \(CSP\) 了,还是啥都不会。
赶紧打几个板子复习一下,让自己认识到自己有多渣然后好好努力吧。
P1886 滑动窗口 /【模板】单调队列
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 1e6 + 10;
int n, k;
int a[N], q[N];
inline void fmin(){
int head = 1, tail = 0;
for(int i = 1; i <= n; i++){
while(head <= tail && q[head] <= i - k) head++;
while(head <= tail && a[i] <= a[q[tail]]) tail--;
q[++tail] = i;
if(i >= k)
printf("%d ", a[q[head]]);
}
puts("");
}
inline void fmax(){
int head = 1, tail = 0;
for(int i = 1; i <= n; i++){
while(head <= tail && q[head] <= i - k) head++;
while(head <= tail && a[i] >= a[q[tail]]) tail--;
q[++tail] = i;
if(i >= k)
printf("%d ", a[q[head]]);
}
puts("");
}
int main(){
n = read(), k = read();
for(int i = 1; i <= n; i++)
a[i] = read();
fmin();
fmax();
return 0;
}
P5788 【模板】单调栈
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 3e6 + 10;
int n;
int a[N], stk[N], top;
int ans[N];
int main(){
n = read();
for(int i = 1; i <= n; i++)
a[i] = read();
for(int i = n; i >= 1; i--){
while(top && a[stk[top]] <= a[i]) top--;
ans[i] = stk[top];
stk[++top] = i;
}
for(int i = 1; i <= n; i++)
printf("%d ", ans[i]);
puts("");
return 0;
}
P3382 【模板】三分法
#include <iostream>
#include <cstdio>
#include <algorithm>
#define exp 1e-8
using namespace std;
int n;
double l, r;
double a[20];
inline double qpow(double a, int b){
double res = 1;
while(b){
if(b & 1) res = res * a;
a = a * a;
b >>= 1;
}
return res;
}
inline double f(double x){
double res = 0;
for(int i = 1; i <= n + 1; i++)
res += a[i] * qpow(x, n - i + 1);
return res;
}
int main(){
scanf("%d%lf%lf", &n, &l, &r);
for(int i = 1; i <= n + 1; i++)
scanf("%lf", &a[i]);
while(r - l > exp){
double lmid = (l + r) / 2;
double rmid = (lmid + r) / 2;
if(f(lmid) > f(rmid)) r = rmid;
else l = lmid;
}
printf("%.5f\n", l);
return 0;
}
P3374 【模板】树状数组 1
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 5e5 + 10;
int n, m;
int c[N];
inline void update(int x, int y){
for(; x <= n; x += x & (-x))
c[x] += y;
}
inline int query(int x){
int res = 0;
for(; x; x -= x & (-x))
res += c[x];
return res;
}
int main(){
n = read(), m = read();
for(int i = 1; i <= n; ++i){
int x = read();
update(i, x);
}
while(m--){
int op = read(), x = read(), y = read();
if(op == 1) update(x, y);
else printf("%d\n", query(y) - query(x - 1));
}
return 0;
}
P3368 【模板】树状数组 2
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 5e5 + 10;
int n, m;
int c[N];
inline void add(int x, int y){
for(; x <= n; x += x & (-x))
c[x] += y;
}
inline int query(int x){
int res = 0;
for(; x; x -= x & (-x))
res += c[x];
return res;
}
int main(){
n = read(), m = read();
int last = 0;
for(int i = 1; i <= n; i++){
int x = read();
add(i, x - last), last = x;
}
while(m--){
int op = read(), x = read();
if(op == 1){
int y = read(), k = read();
add(x, k), add(y + 1, -k);
}else printf("%d\n", query(x));
}
return 0;
}
P3811 【模板】乘法逆元
#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
const ll N = 3e6 + 10;
ll n, mod;
ll inv[N];
signed main(){
scanf("%lld%lld", &n, &mod);
inv[1] = 1;
puts("1");
for(ll i = 2; i <= n; i++){
inv[i] = mod - mod / i * inv[mod % i] % mod;
printf("%lld\n", inv[i]);
}
return 0;
}
P3375 【模板】KMP字符串匹配
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e6 + 10;
char a[N], b[N];
int nxt[N];
int n, m;
int main(){
scanf("%s%s", a + 1, b + 1);
n = strlen(a + 1), m = strlen(b + 1);
nxt[1] = 0;
for(int i = 2, j = 0; i <= m; i++){
while(j && b[i] != b[j + 1]) j = nxt[j];
if(b[i] == b[j + 1]) j++;
nxt[i] = j;
}
for(int i = 1, j = 0; i <= n; i++){
while(j && a[i] != b[j + 1]) j = nxt[j];
if(a[i] == b[j + 1]) j++;
if(j == m){
printf("%d\n", i - j + 1);
j = nxt[j];
}
}
for(int i = 1; i <= m; i++)
printf("%d ", nxt[i]);
puts("");
return 0;
}
P3379 【模板】最近公共祖先(LCA)
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 5e5 + 10;
int n, m, s;
struct node{
int v, nxt;
}edge[N << 1];
int head[N], tot;
inline void add(int x, int y){
edge[++tot] = (node){y, head[x]};
head[x] = tot;
}
int fa[N], son[N], siz[N], dep[N];
inline void dfs1(int x, int p){
fa[x] = p, dep[x] = dep[p] + 1, siz[x] = 1;
for(int i = head[x]; i; i = edge[i].nxt){
int y = edge[i].v;
if(y == p) continue;
dfs1(y, x);
siz[x] += siz[y];
if(!son[x] || siz[y] > siz[son[x]])
son[x] = y;
}
}
int top[N], dfn[N], cnt;
inline void dfs2(int x, int topfa){
top[x] = topfa, dfn[x] = ++cnt;
if(!son[x]) return;
dfs2(son[x], topfa);
for(int i = head[x]; i; i = edge[i].nxt){
int y = edge[i].v;
if(y == fa[x] || y == son[x]) continue;
dfs2(y, y);
}
}
inline int lca(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
int main(){
n = read(), m = read(), s = read();
for(int i = 1; i < n; i++){
int u = read(), v = read();
add(u, v), add(v, u);
}
dfs1(s, 0), dfs2(s, s);
while(m--){
int u = read(), v = read();
printf("%d\n", lca(u, v));
}
return 0;
}
P1939 【模板】矩阵加速(数列)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
const ll mod = 1e9 + 7;
ll T, n;
struct matrix{
ll num[5][5];
matrix(){
memset(num, 0, sizeof(num));
}
matrix operator * (const matrix &b) const{
matrix r;
for(ll i = 1; i <= 3; i++)
for(ll j = 1; j <= 3; j++)
for(ll k = 1; k <= 3; k++)
r.num[i][j] = (r.num[i][j] + num[i][k] * b.num[k][j]) % mod;
return r;
}
matrix operator ^ (ll p) const{
matrix r, a;
memcpy(a.num, num, sizeof(num));
r.num[1][1] = r.num[2][2] = r.num[3][3] = 1;
for(; p; p >>= 1, a = a * a)
if(p & 1) r = r * a;
return r;
}
}f, A;
signed main(){
scanf("%lld", &T);
while(T--){
scanf("%lld", &n);
A.num[1][1] = A.num[1][2] = A.num[3][1] = A.num[2][3] = 1;
f.num[1][1] = f.num[1][2] = f.num[1][3] = 1;
if(n <= 3){
puts("1");
continue;
}
// for(ll i = 1; i <= 10; i++){
// f = f * A;
// cout << f.num[1][1] << " " << " " << f.num[1][2] << " " << f.num[1][3] << endl;
// }
printf("%lld\n", (f * (A ^ (n - 3))).num[1][1]);
}
return 0;
}
P3385 【模板】负环
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int N = 2e3 + 10;
const int M = 3e3 + 10;
int T, n, m;
struct node{
int v, w, nxt;
}edge[M << 1];
int head[N], tot;
inline void add(int x, int y, int z){
edge[++tot] = (node){y, z, head[x]};
head[x] = tot;
}
int dis[N], vis[N], t[N];
inline bool spfa(){
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
memset(t, 0, sizeof(t));
dis[1] = 0, vis[1] = t[1] = 1;
queue <int> q;
q.push(1);
while(!q.empty()){
int x = q.front();
q.pop();
vis[x] = 0;
for(int i = head[x]; i; i = edge[i].nxt){
int y = edge[i].v;
if(dis[y] > dis[x] + edge[i].w){
dis[y] = dis[x] + edge[i].w;
if(!vis[y]){
if((++t[y]) >= n) return 1;
vis[y] = 1;
q.push(y);
}
}
}
}
return 0;
}
int main(){
scanf("%d", &T);
while(T--){
memset(head, 0, sizeof(head));
tot = 0;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
if(w >= 0) add(u, v, w), add(v, u, w);
else add(u, v, w);
}
puts(spfa() ? "YES" : "NO");
}
return 0;
}
P3865 【模板】ST 表
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 1e5 + 10;
int n, m;
int f[N][20];
int main(){
n = read(), m = read();;
for(int i = 1; i <= n; i++){
int a = read();
f[i][0] = a;
}
for(int j = 1; j <= 20; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
while(m--){
int l = read(), r = read();
int k = log2(r - l + 1);
printf("%d\n", max(f[l][k], f[r - (1 << k) + 1][k]));
}
return 0;
}
P4549 【模板】裴蜀定理
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int n, ans;
inline int gcd(int a, int b){
if(!b) return a;
return gcd(b, a % b);
}
int main(){
scanf("%d%d", &n, &ans);
if(ans < 0) ans = -ans;
for(int i = 2, x; i <= n; i++){
scanf("%d", &x);
if(x < 0) x = -x;
ans = gcd(ans, x);
}
printf("%d\n", ans);
}
P4779 【模板】单源最短路径(标准版)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int N = 1e5 + 10;
int n, m, s;
struct Que{
int x, dis;
bool operator < (const Que &b) const{
return dis > b.dis;
}
};
struct node{
int v, w, nxt;
}edge[N << 2];
int head[N], tot;
int dis[N];
inline void add(int x, int y, int z){
edge[++tot].v = y;
edge[tot].w = z;
edge[tot].nxt = head[x];
head[x] = tot;
}
inline void dijkstra(int s){
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
priority_queue <Que> q;
q.push((Que){s, 0});
while(!q.empty()){
Que now = q.top();
q.pop();
int x = now.x;
if(dis[x] < now.dis) continue;
for(int i = head[x]; i; i = edge[i].nxt){
int y = edge[i].v;
if(dis[y] > dis[x] + edge[i].w){
dis[y] = dis[x] + edge[i].w;
q.push((Que){y, dis[y]});
}
}
}
}
int main(){
n = read(), m = read(), s = read();
for(int i = 1; i <= m; i++){
int u = read(), v = read(), w = read();
add(u, v, w);
}
dijkstra(s);
for(int i = 1; i <= n; i++)
printf("%d ", dis[i]);
puts("");
return 0;
}