关于心态
- 厕所是个好地方.
- 考虑部分分.
- 乱搞.
- 能 dp 就 dp.
- 检查傻逼错误, 先看一遍代码再输出调试内容.
- 考虑被投食.
对拍 (in linux)
首先需要正解(你认为的)编译生成的程序 std
和暴力代码的编译生成的程序 slow
.
在同一文件夹写出 random.cpp
自动生成数据为 q.in
, 这里补充较好的 srand()
方法.
srand(clock()); // clock() 获取当前程序运行时间, 返回 long, 包含于 time.h
srand(time(0));
然后编写程序 checker.cpp
, 进行对拍.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
inline void sovle (int t) {
printf("=== Case %d ===\n", t);
system("./random"); // 生成数据
system("./slow"); // 运行暴力
long s1 = clock();
system("./std"); // 运行正解
long s2 = clock();
if (system("diff std.out slow.out"))
printf("WA\n");
else
printf("AC\n");
printf("%ldms\n\n", s2 - s1);
}
int main () {
int t = 30;
for (int i = 1; i <= t; i++)
sovle(i);
return 0;
}
常用技巧
__int128
利用 __int128 解决 \(a+b\) 问题
#include <stdio.h>
#define lll __int128
#define ulll __uint128_t
inline lll read () {
char ch = getchar();
lll ret = 0, c = 1;
while (1) {
if (ch >= '0' && ch <= '9')
break;
if (ch == '-')
c = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
ret = ret * 10 + ch - '0';
ch = getchar();
}
ret = ret * c;
return ret;
}
inline void write (lll x) {
if (x < 0) printf("-"), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int main () {
lll x, y; // sovle the a + b problem by __int128
x = read(), y = read();
write(x + y);
return 0;
}
快速读入与快速输出
见 __int128 部分
register
已经没用了, 哭哭.
数组大小
int a[3e8];
大约占 \(120MB\)
模板
线段树
#include <stdio.h>
#define ll long long
int n;
ll P;
int L[400003], R[400003];
ll lazy[400003], lazy2[400003], sum[400003];
ll a[100003];
inline void build (int p, int l, int r) {
lazy[p] = 0;
lazy2[p] = 1;
L[p] = l, R[p] = r;
if (l == r) {
sum[p] = a[l] % P;
return;
}
int mid = (l + r) / 2;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
sum[p] = (sum[p * 2] + sum[p * 2 + 1]) % P;
return;
}
inline void spread (int p) {
sum[p * 2] = sum[p * 2] * lazy2[p] % P;
sum[p * 2] = (sum[p * 2] + lazy[p] *(ll)(R[p * 2] - L[p * 2] + 1)) % P;
sum[p * 2 + 1] = sum[p * 2 + 1] * lazy2[p] % P;
sum[p * 2 + 1] = (sum[p * 2 + 1] + lazy[p] * (ll)(R[p * 2 + 1] - L[p * 2 + 1] + 1)) % P;
lazy[p * 2] = (lazy[p * 2] * lazy2[p] + lazy[p]) % P;
lazy[p * 2 + 1] = (lazy[p * 2 + 1] * lazy2[p] + lazy[p]) % P;
lazy2[p * 2] = (lazy2[p * 2] * lazy2[p]) % P;
lazy2[p * 2 + 1] = (lazy2[p * 2 + 1] * lazy2[p]) % P;
lazy[p] = 0;
lazy2[p] = 1;
return;
}
inline void change (int p, int l, int r, ll x) {
if (l <= L[p] && R[p] <= r) {
lazy[p] = (lazy[p] + x) % P;
sum[p] = (sum[p] + x * (ll)(R[p] - L[p] + 1)) % P;
return;
}
spread(p);
int mid = (L[p] + R[p]) / 2;
if (l <= mid)
change(p * 2, l, r, x);
if (r > mid)
change(p * 2 + 1, l, r, x);
sum[p] = (sum[p * 2] + sum[p * 2 + 1]) % P;
return;
}
inline void change2 (int p, int l, int r, ll x) {
if (l <= L[p] && R[p] <= r) {
lazy[p] = lazy[p] * x % P;
lazy2[p] = lazy2[p] * x % P;
sum[p] = sum[p] * x % P;
return;
}
spread(p);
int mid = (L[p] + R[p]) / 2;
if (l <= mid)
change2(p * 2, l, r, x);
if (r > mid)
change2(p * 2 + 1, l, r, x);
sum[p] = (sum[p * 2] + sum[p * 2 + 1]) % P;
return;
}
inline ll query (int p, int l, int r) {
if (l <= L[p] && R[p] <= r)
return sum[p];
spread(p);
int mid = (L[p] + R[p]) / 2;
ll ans = 0;
if (l <= mid)
ans = (ans + query(p * 2, l, r)) % P;
if (r > mid)
ans = (ans + query(p * 2 + 1, l, r)) % P;
return ans;
}
int main() {
int m;
scanf("%d %d %lld", &n, &m, &P);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
for (int i = 1; i <= m; i++) {
int a, b, c; ll d;
scanf("%d %d %d", &a, &b, &c);
if (a == 1) {
scanf("%lld", &d);
change2(1, b, c, d);
}
else if (a == 2) {
scanf("%lld", &d);
change(1, b, c, d);
}
else
printf("%lld\n", query(1, b, c));
}
return 0;
}
lca 与 最小生成树 (其实是 [NOIP2013 提高组] 货车运输 的代码)
// Step 1, make the map to a tree (kursual)
// Step 2, lca() to find out who R their the youngest father
// Step 3, check the road one by one to find out the answer
#include <stdio.h>
#include <algorithm>
#define re register
#define ri register int
#define min(x, y) ((x) < (y) ? (x) : (y))
int n, m;
int head[10003], last[20003], to[20003], val[20003], ccnt = 0;
#define addedge(x, y, z) to[++ccnt] = y, val[ccnt] = z, last[ccnt] = head[x], head[x] = ccnt
struct EDGE {
int x, y, z;
inline bool const operator < (const EDGE &rhs) const {
return z > rhs.z;
}
} edge[50003];
int lg[10003];
int depth[10003], father[10003][53], cvl[10003];
int fa[10003]; // びんーかじ!
inline int getfa (int x); inline void kursual ();
void dfs (int cur, int dis, int fat); inline int lca (int x, int y);
inline int kagari (int x, int y) {
if (fa[x] != fa[y])
return -1;
ri acl = lca(x, y);
ri ret = 0x3F3F3F3F;
while (x != acl)
ret = min(ret, cvl[x]),
x = father[x][0];
while (y != acl)
ret = min(ret, cvl[y]),
y = father[y][0];
return ret;
}
int main () {
// freopen("truck.in", "r", stdin);
// freopen("truck.out", "w", stdout);
scanf("%d %d", &n, &m);
for (ri i = 1; i <= m; i++)
scanf("%d %d %d", &edge[i].x, &edge[i].y, &edge[i].z);
for (ri i = 1; i <= n; i++)
lg[i] = lg[i - 1] + (1 << lg[i - 1] == i ? 1 : 0);
kursual();
dfs(1, 1, 1);
for (ri i = 1; i <= n; i++)
fa[i] = getfa(i);
ri q;
scanf("%d", &q);
while (q--) {
ri x, y;
scanf("%d %d", &x, &y);
ri hiko = kagari(x, y);
printf("%d\n", hiko);
}
return 0;
}
/***** クラソァ *****/
inline int getfa (int x) {
if (x == fa[x])
return x;
fa[x] = getfa(fa[x]);
return fa[x];
}
inline void kursual () {
std:: sort(edge + 1, edge + m + 1);
for (ri i = 1; i <= n; i++)
fa[i] = i;
for (ri i = 1; i <= m; i++) {
ri x = edge[i].x, y = edge[i].y, z = edge[i].z;
ri fx = getfa(x), fy = getfa(y);
if (fx == fy)
continue;
addedge(x, y, z);
addedge(y, x, z);
fa[fx] = fy;
}
return;
}
/***** LCA *****/
inline void dfs (int cur, int dis, int fat) {
depth[cur] = dis;
father[cur][0] = fat;
for (ri i = 1; i <= lg[depth[cur]]; i++)
father[cur][i] = father[father[cur][i - 1]][i - 1];
for (ri i = head[cur]; i; i = last[i])
if (to[i] != fat)
dfs(to[i], dis + 1, cur),
cvl[to[i]] = val[i];
}
inline int lca (int x, int y) {
if (depth[x] < depth[y])
x ^= y, y ^= x, x ^= y;
while (depth[x] > depth[y])
x = father[x][lg[depth[x] - depth[y]] - 1];
if (x == y)
return x;
for (ri i = lg[depth[x] - 1]; i >= 0; i--)
if (father[x][i] != father[y][i])
x = father[x][i], y = father[y][i];
return father[x][0];
}