关于心态

  • 厕所是个好地方.
  • 考虑部分分.
  • 乱搞.
  • 能 dp 就 dp.
  • 检查傻逼错误, 先看一遍代码再输出调试内容.
  • 考虑被投食.

对拍 (in linux)

idea

首先需要正解(你认为的)编译生成的程序 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];
}
( ゚∀゚)o彡゜ ヒーコー ヒーコー!