模板

今天(2017.11.08)开始打板子。

 

一、读入输出优化

  注意:数组类型和负号。

#include <cstdio>

int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch > '9' || ch < '0') ch == '-' && (f = -1), ch = getchar();
	while (ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
	return x * f;
}

void pf(int x) {                         // 如果x小于10,直接输出,否则先输出十位及以上部分,然后输出个位。如果是负数,先输出‘-’,再当成正数输出即可。
	if (x < 0) putchar('-'), x = -x;       // 递归版输出优化,听说效率玄学。
	if (x > 9) pf(x / 10);
	putchar(x % 10 + '0');
}
	
int main() {
	int a = read();
	pf(a);
}                        

 

二、并查集

  例题传送门

  模板:

#include <cstdio>

const int MAXN = 5000 + 7;

int dad[MAXN], n, m, p;
/******************只有这两行******************************************************/
int getdad(int x) {
	return x == dad[x] ? x : getdad(dad[x]);
}

void join(int x, int y) {
	int a = getdad(x), b = getdad(y);
	if (a != b) dad[a] = getdad(b);
}
/*******************是主代码。*****************************************************/

int main() { scanf("%d%d%d", &n, &m, &p); for (int i = 1; i <= n; i++) dad[i] = i; for (int i = 1, x, y; i <= m; i++) scanf("%d%d", &x, &y), join(x, y); for (int i = 1, x, y; i <= p; i++) { scanf("%d%d", &x, &y); int a = getdad(x), b = getdad(y); puts(a == b ? "Yes\n" : "No\n"); } return 0; }

 

三、树状数组与线段树

  传送门

  树状数组:http://blog.csdn.net/qq_21841245/article/details/43956633

  biu

树状数组针对的是加上某值,如果是“改为某值”,则操作时加上的是(要改的值-原本的值)。

#include <cstdio>

const int MAXN = 1e5 + 7;

int n, m;

struct Node {
	int tree[MAXN];
	void add(int x, int v) {			// 单点更新 
		while (x <= n) {
			tree[x] += v;
			x += x & (-x);		
		}
	}	
	
	int sum(int k) {					// 区间求和 
		int ans = 0;
		while (k) {	
			ans += tree[k];
			k -= k & (-k);
		}
		return ans;
	}
} T;

int main() {
	scanf("%d", &n);
	for (int i = 1, v; i <= n; i++) {
		scanf("%d", &v);
		T.add(i, v);
	}
	scanf("%d", &m);
	for (int i = 1; i <= m; i++) {
		int x, a, b;
		scanf("%d%d%d", &x, &a, &b);
		if (x == 1) T.add(a, b);
		else printf("%d\n", T.sum(b) - T.sum(a - 1));
	}
	
	return 0;
}

 

四、Kruskal

  传送

#include <cstdio>
#include <algorithm>

const int MAXN = 107 * 3;

int n, m, cnt, dad[MAXN], size[MAXN], ans;

struct Edge {
	int from, to, pow;
	bool operator<(const Edge p) const {
		return pow < p.pow;
	}
} edge[MAXN];

int get(int x) {
	return dad[x] == x ? x : get(dad[x]);
}

void join(int x, int y) {
	int a = get(x), b = get(y);
	if (size[a] < size[b]) dad[a] = b, size[b] += size[a];
	else dad[b] = a, size[a] += size[b];
}

int main() {
	while (scanf("%d%d", &n ,&m) == 2) {
		ans = 0;
		if (n == 0) break;
		for (int i = 1; i <= m; i++) dad[i] = i, size[i] = 1;
		for (int i = 1; i <= n; i++) {
			int x, y, z;
			scanf("%d%d%d", &x, &y, &z);
			edge[i].from = x;
			edge[i].pow = z;
			edge[i].to = y; 
		}
		
		std::sort(edge + 1, edge + n + 1);
		
		int cnt = 0;
		for (int i = 1; i <= n; i++) {
			int f = edge[i].from, t = edge[i].to;
			if (get(f) != get(t)) {
				join(f, t);
				cnt++;
				ans += edge[i].pow;
			}
		}
		
		if (cnt < m - 1) printf("?\n");
		else printf("%d\n", ans);
	}
	return 0;
} 

 

五、归并排序

  应用:求逆序对

#include <iostream>
#include <cstdio>

const int MAXN = 100050;

int n, a[MAXN], l[MAXN];
long long count;
 
void M(int s, int mid , int e) {
	int i = s, j = mid + 1, k = 1;
	
	while (i <= mid && j <= e) {
		if (a[i] <= a[j]) l[k++] = a[i++];
		else l[k++] = a[j++], count += mid + 1 - i;						// 求逆序对数关键操作 
	}
	
	while (i <= mid) l[k++] = a[i++];
	while (j <= e) l[k++] = a[j++];
	
	for (int i = 1, j = s; j <= e; j++, i++) a[j] = l[i];				// !!
}

void MS(int s, int e) {
	if (!(e - s)) return ;
	else {
		int mid = (e + s) / 2;	
		MS(s, mid);
		MS(mid + 1, e);
		M(s, mid, e);
	}
}

int main() {
	scanf("%d", &n);
	
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);

	MS(1, n);
	
	printf("%lld\n", count);

	for (int i = 1; i <= n; i++) printf("%d ", a[i]);
	
	return 0;
}

 

六、生无可恋的线段树

#include <cstdio>
#include <algorithm>

const int MAXN = 1e5 + 7;

int n, m;

struct Node {
	int tag, pow, l, r;
	Node *lc, *rc;
	Node () {}
	Node (int l, int r, Node *lc, Node *rc) : tag(0), pow(0), l(l), r(r), lc(lc), rc(rc) {}
} *cur, *root, node[MAXN * 4];

Node *Build(int l, int r) {
	int mid = l + ((r - l)>> 1);
	return l == r ? new (cur++)Node(l, r, NULL, NULL) : new (cur++)Node(l, r, Build(l, mid), Build(mid + 1, r)); 
}

void Cover(Node *v, int delta) {
	v->pow += (v->r - v->l + 1) * delta;
	v->tag += delta; 
}

void PushDown(Node *v) {
	if (v->tag) Cover(v->lc, v->tag), Cover(v->rc, v->tag), v->tag = 0;
}

void Update(Node *v, int l, int r, int delta) {
	if (v->r < l || v->l > r) return ;
	else if (l <= v->l && r >= v->r) Cover(v, delta);
	else PushDown(v), Update(v->lc, l, r, delta), Update(v->rc, l, r, delta), v->pow = v->lc->pow + v->rc->pow; 
}
int Q(Node *v, int l, int r) {
	if (v->r < l || v->l > r) return 0;
	else if (l <= v->l && r >= v->r) return v->pow;
	else return PushDown(v), Q(v->lc, l, r) + Q(v->rc, l, r); 
}

int main() {
	cur = node;
	scanf("%d", &n);
	root = Build(1, n);
	
	for (int i = 1, v; i <=n; i++) 
		scanf("%d", &v), Update(root, i, i, v); 
	
	scanf("%d", &m);
	for (int i = 1; i <= m; i++) {
		int z, x, y;
		scanf("%d%d%d", &z, &x, &y);
		if (z == 1) Update(root, x, x, y);
		else printf("%d\n", Q(root, x, y));
	}
	return 0;
} 

 每次写线段树总会出点错... ...

  这次份的:

  ① 不加 #include <algorithm> 调了一个下午才发现... ...

   后果:  

      

      

    ② Q(){} 函数最后那种情况没写 ‘+’。

      

    ③ 每次写都犯的:

      Update 和 Q 里第二种情况是

      当前节点代表的区间被要进行操作的区间包含

      而不是 要进行操作的区间被当前节点代表的区间包含。

 

七、二分

#include <cstdio>

const int MAXN = 5e4 + 7;

int s, n, m, a[MAXN];

int check(int x) {
	int last = 0, re = 0;
	for (int i = 1; i <= n + 1; i++) 
		if (a[i] - last < x) re++;
		else last = a[i];
	
	return re;
}

int main() {
	scanf("%d%d%d", &s, &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	a[n + 1] = s;
	
	int l = 1, r = s, ans = 0;
	while (l <= r) {
		int mid = (l + r) >> 1;
		int f = check(mid);
//		printf("when mid = %d, f = %d\n", mid, f);
		if (f <= m) l = mid + 1, ans = mid;
		else r = mid - 1; 
	}
	
	printf("%d\n", ans);
	
	return 0;
} 

  错误详见

 

posted @ 2017-11-09 20:42  E-Valley  阅读(246)  评论(0)    收藏  举报