OI标程整理

标程整理

数论

欧拉函数#1

int get_phi () {
	for (int i = 1; i <= Maxn; ++i) phi[i] = i;
	for (int i = 2; i <= Maxn; ++i)
		if (phi[i] == i) {
			for (int j = i; j <= x; j += i)
				phi[j] -= phi[j] / i;
		}
}

欧拉函数#2

void get_phi () {
	phi[1] = 1;
	for (int i = 2; i <= Maxn; ++i) {
		if (!phi[i]) {
			phi[i] = i - 1;
			prime[++cnt] = i;
		}
		for (int j = 1; j <= cnt && i * prime[j] <= Maxn; ++j) {
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			else phi[i * prime[j]] = phi[i] * phi[prime[j]];
		}
	}
	
	for (int i = 3; i <= Maxn; ++i)
		phi[i] += phi[i - 1];
}

欧拉函数#3

void get_phi (int n) {
	int res = n;
	for (int i = 2 ; i <= n / i ; i ++) {
    	if (n % i == 0) {
        	res = res / i * (i - 1);
       		while (n % i == 0)  n /= i;
    	}
	}
	if (n > 1) res = res / n * (n - 1);
	return res;
}

扩展欧几里得

int ex_gcd (int a, int b, int &x, int &y) {
	if (b == 0) {
		x = n / a; y = 0;
		return a;
	}
	else {
		int r = ex_gcd (b, a % b, x, y);
		int t = x;
		x = y;
		y = t - a / b * y;
		return r;
	}
}

逆元

inv[1] = 1;
for (int i = 2; i <= n; ++i) {
	inv[i] = (p - p / i) * inv[p % i] % p;
}

中国剩余定理(n组余数关系)

cin >> n;
for (int i = 1; i <= n; ++i) {
	cin >> a[i] >> b[i];
	sum = sum * a[i];
}
	
for (int i = 1; i <= n; ++i) {
	sum /= a[i];		
	x = y = 0;
	ex_gcd (sum, a[i], x, y); //求逆元,使余数归一
	x = (x + a[i]) % a[i];
	ans = (ans + x * sum * b[i]) % (sum * a[i]); //通过相乘产生当前余数
	sum *= a[i];
}
	
cout << ans % sum << endl;

线性筛(同时统计最小因数)

for (int i = 2; i <= n; ++i) mindiv[i] = i;
for (int i = 2; i <= n; ++i) {
	if (mindiv[i] == i) prime[++cnt] = i;
	for (int j = 1; j <= cnt && i * prime[j] <= n; ++j) {
		mindiv[i * prime[j]] = prime[j];
		if (i % prime[j] == 0) break;
	}
}

最大公约数

int gcd (int x, int y) {
	if (y == 0) return x;
	return gcd (y, x % y);
}

图论

加边

inline void add (int x, int y){
	edge[++sum].next = head[x];
	edge[sum].from = x;
	edge[sum].to = y;
	head[x] = sum;
}

Kruskal

int kruskal(){
	int m = 0, ans = 0;
	for (int i = 0; i < n; ++i)
		fa[i] = i;
	for (int i = 1; i <= js; ++i){
		int fu = find(edg[i].u);
		int fv = find(edg[i].v);
		if (fu != fv){
			ans += edg[i].w;
			fa[fu] = fv;
			m++;
			if (m == n - 1) break;
		}
	}
	return ans;
}

Prim

int prim () {
	for (int i = 0; i < n; ++i) {
		dis[i] = g[1][i];
	}
	
	memset (vis, 0, sizeof (vis));
	vis[1] = true;
	int ans = 0, pv;
	for (int i = 1; i < n; ++i) {
		int minv = 0x3f3f3f3f;
		for (int j = 0; j < n; ++j) 
			if (!vis[j] && dis[j] < minv) {
				minv = dis[j];
				pv = j;
			}
		ans += dis[pv];
		vis[pv] = 1;
		for (int j = 0; j < n; ++j) 
			if (!vis[j]) dis[j] = min (dis[j], g[pv][j]);
	}
	return ans;
}

Tarjan

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e4 + 15;
int n, m, sum, tim, top, s, p[maxn], head[maxn], sd[maxn], dfn[maxn], low[maxn], sta[maxn], vh[maxn], h[maxn], in[maxn], dis[maxn];
struct Edge{
	int to, next, from;
}edge[maxn * 10], ed[maxn * 10];

inline void add (int x, int y);
inline int Topu();

inline void Tarjan (int x){
	low[x] = dfn[x] = ++tim;
	sta[++top] = x;
	vh[x] = 1;
	
	for (int i = head[x]; i; i = edge[i].next){
		int v = edge[i].to;
		if (!dfn[v]){
			Tarjan (v);
			low[x] = min (low[x], low[v]);
		}
		else if (vh[v])
				low[x] = min (low[x], low[v]);
	}
	
	if (dfn[x] == low[x]){
		int y;
		while (y = sta[top--]){
			sd[y] = x;
			vh[y] = 0;
			if (x == y) break;
			p[x] += p[y];
		}
	}
}

int main(){
	ios::sync_with_stdio (false);
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
		cin >> p[i];
	for (int i = 1; i <= m; ++i){
		int u, v;
		cin >> u >> v;
		add (u, v);
	}
	
	for (int i = 1; i <= n; ++i)
		if (!dfn[i]) Tarjan (i);
	for (int i = 1; i <= m; ++i){
		int x = sd[edge[i].from], y = sd[edge[i].to];
		if (x != y){
			ed[++s].next = h[x];
			ed[s].to = y;
			ed[s].from = x;
			h[x] = s;
			in[y]++;
		}
	}
	
	cout << Topu() << endl;
	return 0;
}

SPFA

void spfa (int s) {
	queue <int> que;
	memset (dis, 0x3f3f3f3f, sizeof (dis));
	dis[s] = 0;
	que.push (s);
	
	while (!que.empty()) {
		int f = que.front();
		que.pop();
		vh[f] = 0;
		
		for (int i = 0; i < p[f].size(); ++i) {
			node v = p[f][i];
			if (dis[v.to] > dis[f] + v.len) {
				dis[v.to] = dis[f] + v.len;
				if (!vh[v.to]) {
					vh[v.to] = 1;
					que.push (v.to);
				}
			}
		}
	}
}//统计每个点入队次数可以判断有无负回路

Dijkstra

struct node {
	int to, len;
	
	bool operator < (const node x) const {
		return len > x.len;
	}
};

void dijkstra (int s) {
	priority_queue <node> que;
	memset (dis, 0x3f3f3f3f, sizeof (dis));
	dis[s] = 0;
	que.push ({s, 0});
	
	while (!que.empty()) {
		node f = que.top();
		que.pop();
		if (f.len > dis[f.to]) continue;
		
		for (int i = 0; i < p[f.to].size(); ++i) {
			node v = p[f.to][i];
			if (dis[f.to] + v.len < dis[v.to]) {
				dis[v.to] = dis[f.to] + v.len;
				que.push ({v.to, dis[v.to]});
			}
		}
	}
}

Floyd

void floyd () {
	//记得读入的时候去重边(CSP-S T3悲)
	for (int i = 1; i <= n; ++i)
		dis[i][i] = 0;
	for (int k = 1; k <= n; ++k)
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= n; ++j)
				dis[i][j] = min (dis[i][j], dis[i][k] + dis[k][j]);
}

拓扑排序

inline int Topu (){
	queue <int> q;
	int tot = 0;
	for (int i = 1; i <= n; ++i)
		if (sd[i] == i && !in[i]){ //此处在缩点之后使用,所以会有这个数组
			q.push(i);
			dis[i] = p[i];
		}
	
	while (!q.empty()){
		register int k = q.front();
		q.pop();
		for (register int i = h[k]; i; i = ed[i].next){
			register int v = ed[i].to;
			dis[v] = max (dis[v], dis[k] + p[v]);
			in[v]--;
			if (in[v] == 0)
				q.push (v);
		}
	}
	
	int ans = 0;
	for (int i = 1; i <= n; ++i)
		ans = max (ans, dis[i]);
	return ans;
}

割点

树的直径

数据结构

STL

Set
set <data_type> set_name;
set <data_type>::iterator it = the_position_you_want
size() : 返回容器元素个数
clear() : 清空容器元素
empty() : 判断容器是否为空,空返回 true,否则,返回false
begin() : 返回指向第一个元素的迭代器
end() : 返回指向最后一个元素的迭代器
rbegin() : 返回指向最后一个元素的反向迭代器
rend() : 返回指向第一个元素的反向迭代器
lower_bound() : 返回指向等于或大于指定键值元素的迭代器
upper_bound() : 返回指向大于指定键值元素的迭代器
erase (position) : 删除迭代器 position 指向的元素
erase (first, last) : 删除 [first, last) 区间的元素
insert(val) : 插入元素 val
find (val) : 查找元素 val,如果存在返回其迭代器
map
begin() : 返回指向map头部的迭代器
clear() : 删除所有元素
begin() : 返回指向map头部的迭代器
clear() : 删除所有元素
count() : 返回指定元素出现的次数
empty() : 如果map为空则返回true
end() : 返回指向map末尾的迭代器
equal_range() : 返回特殊条目的迭代器对
erase() : 删除一个元素
find() : 查找一个元素
insert() : 插入元素
lower_bound() : 返回键值大于或等于给定元素的第一个位置
upper_bound() : 返回键值大于给定元素的第一个位置
max_size() : 返回可以容纳的最大元素个数
rbegin() : 返回一个指向map尾部的逆向迭代器
rend() : 返回一个指向map头部的逆向迭代器
size() : 返回map中元素的个数

字符串KMP

inline void get_nxt (string s) {
	int j = 0, k = -1;
	nxt[0] = -1;
	while (j < s.size()) {
		if (k == -1 || s[j] == s[k]) nxt[++j] = ++k;
		else k = nxt[k];
	}
}

inline void KMP (string s, string t) {
	int i = 0, j = 0;
	int slen = s.size(), tlen = t.size();
	get_nxt (t);
	
	while (i < slen && j < tlen) {
		if (j == -1 || s[i] == t[j]) {
			i++; j++;
		}
		else j = nxt[j];
		
		if (j == tlen) {
			cout << i - tlen + 1 << endl;
			j = nxt[j];
		}
	}
}

树状数组

int lowbit (int x){
	return x & -x;
}

void modify (int pos, int d){
	while (pos <= n){
		s[pos] += d;
		pos += lowbit(pos);
	}
}

int getnum (int pos){
	int sum = 0;
	while (pos > 0){
		sum += s[pos];
		pos -= lowbit (pos);
	}
	return sum;
}

树状数组(二维)

int lowbit (int x) {
	return x & -x;
}

void modify (int x, int y, int d) {
	for (int i = x; i <= n; i += lowbit (i))
		for (int j = y; j <= n; j += lowbit (j))
			s[i][j] += d;
}

int getsum (int x, int y) {
	int sum = 0;
	for (int i = x; i > 0; i -= lowbit (i))
		for (int j = y; j > 0; j -= lowbit (j))
			sum += s[i][j];
	return sum;
}

并查集

int find (int x){
	if (fa[x] == x) return x;
	return fa[x] = find (fa[x]);
}
int Union (int x, int y){
	fa[find(y)] = find (x);
}

线段树

const int MAXN = 1e5 + 10;
struct node {
	int l, r, s, note;
	node (int _l = 0, int _r = 0, int _s = 0, int _note = 0) {
		l = _l;
		r = _r;
		s = _s;
		note = _note;
	}
};
int n, m, op;
node tree [MAXN * 4];

inline void create (int root , int l, int r) {
	tree[root] = node (l, r, 0, 0);
	if (l < r) {
		int mid = (l + r) / 2;
		create (root * 2, l, mid);
		create (root * 2 + 1, mid + 1, r);
	}
}

inline void modify (int root, int x, int y, int d) {
	tree[root].s += (y - x + 1) * d;
	if (x == tree[root].l && y == tree[root].r) {
		tree[root].note += d;
		return;
	}
	
	int mid = (tree[root].l + tree[root].r) / 2;
	tree[root * 2].note += tree[root].note;
	tree[root * 2].s += (mid - tree[root].l + 1) * tree[root].note;
	tree[root * 2 + 1].note += tree[root].note;
	tree[root * 2 + 1].s += (tree[root].r - mid) * tree[root].note;
	tree[root].note = 0;
	
	if (x > mid) modify (root * 2 + 1, x, y, d);
	else if (y <= mid) modify (root * 2, x, y, d);
	else {
		modify (root * 2, x, mid, d);
		modify (root * 2 + 1, mid + 1, y, d);	
	}
}

inline int getsum (int root, int x, int y) {
	if (x == tree[root].l && y == tree[root].r) return tree[root].s;
	
	int mid = (tree[root].l + tree[root].r) / 2;
	tree[root * 2].note += tree[root].note;
	tree[root * 2].s += (mid - tree[root].l + 1) * tree[root].note;
	tree[root * 2 + 1].note += tree[root].note;
	tree[root * 2 + 1].s += (tree[root].r - mid) * tree[root].note;
	tree[root].note = 0;
	
	if (x > mid) return getsum (root * 2 + 1, x, y);
	else if (y <= mid) return getsum (root * 2, x, y);
	else return getsum (root * 2, x, mid) + getsum (root * 2 + 1, mid + 1, y);
}

ST表

for (int i = 1; i <= n; ++i) 
	cin >> f[i][0];
lg[1] = 0;
for (int i = 2; i <= n; ++i)
	lg[i] = lg[i / 2] + 1;
	
for (int j = 1; j <= lg[n]; ++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]);
	
int l, r;		
for (int i = 1; i <= m; ++i) {
	cin >> l >> r;
	int p = r - l + 1;
	cout << max(f[l][lg[p]], f[r - (1 << lg[p]) + 1][lg[p]]) << endl;
}

链表

#include <bits/stdc++.h>
using namespace std;

struct node {
	int val, next;
};

node a[110];
int n, head;

int main(){
	cin >> n;
	a[head].next = -1;
	for (int i = 1; i <= n; ++i){
		cin >> a[i].val;
		int p = head;
		while (a[p].next != -1 && a[a[p].next].val < a[i].val)
			p = a[p].next;
		a[i].next = a[p].next;
		a[p].next = i;
	}
	
	int p = a[head].next;
	while (p != -1){
		cout << a[p].val << " ";
		p = a[p].next;
	}
	cout << endl;
	return 0;
}

LCA

void dfs (int k, int f) { //f:fa
	fa[k][0] = f;
	d[k] = d[f] + 1;
	for (int i = 1; (1 << i) <= d[k]; ++i)
		fa[k][i] = fa[fa[k][i - 1]][i - 1];
	for (int i = 0; i < g[k].size(); ++i) {
		if (g[k][i] == f) continue;
		dfs (g[k][i], k);
	}
}

int LCA (int x, int y) {
	if (d[x] > d[y]) swap (x, y);
	for (int i = 19; i >= 0; --i)
		if ((1 << i) + d[x] <= d[y]) y = fa[y][i];
	if (x == y) return x;
	for (int i = 19; i >= 0; --i) {
		if (fa[x][i] != fa[y][i]) {
			x = fa[x][i];
			y = fa[y][i];
		}
	}
	return fa[x][0];
}

基础算法

二分

快速排序

#include <bits/stdc++.h>
using namespace std;

int n, a[100100];

void quick_sort(int l, int r){
	int x, i, j;
	i = l;
	j = r;
	x = a[(i + j) / 2];
	
	do{
		while(a[i] < x) i++;
		while(a[j] > x) j--;
		
		if(i <= j){
			swap(a[i], a[j]);
			i++; j--;
		}
		
	}while(i <= j);
	
	if(i < r) quick_sort(i, r);
	if(j > l) quick_sort(l, j);
}

int main(){
	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> a[i];

	quick_sort(1, n);
	
	for (int i = 1; i < n; ++i)
		cout << a[i] << " ";
	cout << a[n] << endl;
	return 0;
}

归并排序

#include <bits/stdc++.h>
using namespace std;

int n, a[100010], b[100010];

void merge (int l, int mid, int r){
	int p1 = l, p2 = mid + 1, p3 = l;
	
	while (p1 <= mid && p2 <= r && p3 <= r){
		if (a[p1] <= a[p2]){
			b[p3] = a[p1];
			p3++; p1++;
		}
		else {
			b[p3] = a[p2];
			p3++; p2++;
		}
	}
	while (p1 <= mid && p3 <= r){
		b[p3] = a[p1];
		p3++; p1++;
	}
	while (p2 <= r && p3 <= r){
		b[p3] = a[p2];
		p3++; p2++;
	}
	
	for (int i = l; i <= r; ++i)
		a[i] = b[i];
}

void merge_sort (int l, int r){
	if (l < r){
		int mid = (l + r) / 2;
		merge_sort (l, mid);
		merge_sort (mid + 1, r);
		merge (l, mid, r);
	}
}

int main(){
	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> a[i];
	
	merge_sort (1, n);
	
	for (int i = 1; i <= n; ++i)
		cout << a[i] << " ";
	cout << endl;
	return 0;
}

高精度

struct large{
	int val[10010], len = 0;
	
	void input () {
		string s;
		cin >> s;
		for (len = 0; len < s.size(); ++len)
			val[s.size() - len] = s[len] - '0';
	}
	
	void output () {
		for (int i = len; i >= 1; --i)
			cout << val[i];
	}
	
	bool operator < (const large &x) const {
		if (len > x.len) return false;
		for (int i = 1; i < len; ++i)
			if (val[i] > x.val[i]) return false;
		if (val[len] == x.val[len]) return false;
		return true;
	}
	
	bool operator > (const large &x) const {
		if (len < x.len) return false;
		for (int i = 1; i < len; ++i)
			if (val[i] < x.val[i]) return false;
		if (val[len] == x.val[len]) return false;
		return true;
	}
	
	bool operator == (const large &x) const {
		if (len != x.len) return false;
		for (int i = 1; i <= len; ++i)
			if (val[i] != x.val[i]) return false;
		return true;
	}
	
	
	large operator + (const large &x) const{
		large ans;
		ans.len = max (len, x.len);
		
		for (int i = 1; i <= ans.len; ++i)
			ans.val[i] = val[i] + x.val[i];
		for (int i = 1; i <= ans.len; ++i) {
			if (ans.val[i] / 10) {
				ans.val[i + 1] += ans.val[i] / 10;
				ans.val[i] %= 10;
			}
			if (i == ans.len && ans.val[i + 1]) ans.len++;
		}
		
		return ans;
	}
	
	large operator - (const large &x) const{
		large ans;
		ans.len = max (len, x.len);
		
		for (int i = 1; i <= ans.len; ++i)
			ans.val[i] = val[i] - x.val[i];
		for (int i = 1; i <= ans.len; ++i) {
			if (ans.val[i] < 0) {
				ans.val[i + 1]--;
				ans.val[i] += 10;
			}
		}
		
		while (ans.len > 1 && !ans.val[ans.len]) ans.len--;
		
		return ans;
	}
	
	large operator * (const large & x) const {
		large ans;
		ans.len = len + x.len - 1;
		
		for (int i = 1; i <= len; ++i)
			for (int j = 1; j <= x.len; ++j)
				ans.val[i + j - 1] += val[i] * x.val[j];
		for (int i = 1; i <= ans.len; ++i) {
			if (ans.val[i] / 10) {
				ans.val[i + 1] += ans.val[i] / 10;
				ans.val[i] %= 10;
			}
			if (i == ans.len && ans.val[i + 1]) ans.len++;
		}
		
		while (ans.len > 1 && !ans.val[ans.len]) ans.len--;
		
		return ans;
	}
	
	//I hate dividing very much!!
	
};

快速幂

int qm (int x, int y, int d){
	if (y == 0 || x == 1) return 1;
	if (y == 1) return x % d;
	
	int num = qm (x, y / 2, d);
	if (y % 2) return (((num * num) % d) * (x % d)) % d;
	else return (num * num) % d;
}

第K小的数

nth_element (a + 1,a + k, a + n + 1);

逆序对(归并排序)

#include <bits/stdc++.h>
using namespace std;
long long n, a[600000], ans = 0, b[600000];

void merge(int low_, int mid, int high_){
  	int p1 = low_, p2 = mid + 1, p3 = low_, j;
  
	while(p3 <= high_){
    	if(p1 <= mid && (p2 > high_ || a[p1] <= a[p2])){
      		b[p3] = a[p1];
      		p1++;
    	}
    	else {
      		b[p3] = a[p2];
      		ans += mid - p1 + 1;
      		p2++;
    	}
    	p3++;
  	}
  
  	for(j = low_; j <= high_; ++j)
    	a[j] = b[j];
}

void merge_sort(int low_, int high_){
  	int mid;
  	if(low_ < high_){
    	mid = (low_ + high_) / 2;
    	merge_sort(low_, mid);
    	merge_sort(mid + 1, high_);
    	merge(low_, mid, high_);
  }
}

int main(){
    cin >> n;
    for (int i = 1; i <= n; ++i)
      scanf("%d", &a[i]);
    
    merge_sort (1, n);
    
    cout << ans << endl;
    return 0;
}

逆序对(树状数组)

#include <bits/stdc++.h>
using namespace std;

struct nod{
	int num, id, v;
} a[500010];

int n, s[500010];
long long ans = 0;

bool cmp1(nod p, nod q){
	return p.num < q.num;
}

bool cmp2 (nod p, nod q){
	return p.id < q.id;
}

int lowbit (int x){
	return x & -x;
}

void modify (int pos, int d){
	while (pos <= n){
		s[pos] += d;
		pos += lowbit(pos);
	}
}

int getnum (int pos){
	int sum = 0;
	while (pos > 0){
		sum += s[pos];
		pos -= lowbit (pos);
	}
	return sum;
}

int main(){
	cin >> n;
	for (int i = 1; i <= n; ++i){
		scanf ("%d", &a[i].num);
		a[i].id = i;
	}
	sort (a + 1, a + 1 + n, cmp1);
	a[1].v = 1;
	for (int i = 2; i <= n; ++i)
		if (a[i].num == a[i - 1].num) a[i].v = a[i - 1].v;
		else a[i].v = a[i - 1].v + 1;
	sort (a + 1, a + 1 + n, cmp2);
	
	for (int i = n; i >= 1; --i){
		modify (a[i].v, 1);
		ans += getnum (a[i].v - 1);
	}
	cout << ans << endl;
	return 0;
}

动态统计中位数 (优先队列)

#include <bits/stdc++.h>
using namespace std;

int n, a;
priority_queue <int> y;
priority_queue <int, vector <int>, greater <int> > x;

int main() {
	cin >> n;
	cin >> a;
	cout << a << endl;
	x.push(a);
	for (int i = 2; i <= (n + 1) / 2; i++) {
		cin >> a;
		y.push(a);
		cin >> a;
		y.push(a);
		
		x.push(y.top());
		y.pop();
		x.push(y.top());
		y.pop();
		y.push(x.top());
		x.pop();
		
		cout << x.top() << endl;
	} 
	return 0;
}

动态统计中位数 (链表)

#include <bits/stdc++.h>
using namespace std;

struct num {
	int val, id;
}a[100010];
int n, pos, p_map[100010], ans[50010], nxt[100010], pre[100010];

bool cmp (num x, num y) {
	return x.val < y.val;
}

int main() {
	cin >> n;
	if (!(n % 2)) n--;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i].val;
		a[i].id = i;
	}
	sort (a + 1, a + 1 + n, cmp);
	for (int i = 1; i <= n; ++i)
		p_map[a[i].id] = i;
	for (int i = 1; i <= n; ++i) {
		pre[i] = i - 1;
		nxt[i] = i + 1;
	}
	pre[1] = nxt[n] = -1;
	
	int pos = (n + 1) / 2, cnt;
	for (cnt = 1; cnt * 2 < n; ++cnt) {
		ans[cnt] = a[pos].val;
		int p1 = p_map[n - cnt * 2 + 1], p2 = p_map[n - cnt * 2 + 2];
		if (pre[p1] != -1) nxt[pre[p1]] = nxt[p1];
		if (nxt[p1] != -1) pre[nxt[p1]] = pre[p1];
		if (pre[p2] != -1) nxt[pre[p2]] = nxt[p2];
		if (nxt[p2] != -1) pre[nxt[p2]] = pre[p2];
		if (p1 >= pos && p2 >= pos) pos = pre[pos];
		if (p1 <= pos && p2 <= pos) pos = nxt[pos];
	}
	ans[cnt] = a[pos].val;
	
	for (int i = cnt; i >= 1; --i)
		cout << ans[i] << endl;
	return 0;
}

最长公共子序列

#include <bits/stdc++.h>
using namespace std;

int n, p1[100010], p2[100010], trans[100010], dp[100010], ans = 0;

int ef (int x){
	int l = 0, r = n;
	while (l < r){
		int mid = (l + r) / 2;
		if (dp[mid] == x) l = mid + 1;
		if (dp[mid] > x) r = mid;
		if (dp[mid] < x) l = mid + 1;
	}
	return l;
}

int main(){
	memset (dp, 0x3f3f3f3f, sizeof(dp));
	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> p1[i];
	for (int i = 1; i <= n; ++i)
		cin >> p2[i];
		
	for (int i = 1; i <= n; ++i)
		trans[p1[i]] = i;
	for (int i = 1; i <= n; ++i)
		p2[i] = trans[p2[i]];
		
	dp[1] = p2[1]; dp[0] = 0;
	for (int i = 2; i <= n; ++i){
		int pos = ef (p2[i]);
		dp[pos] = p2[i];
		ans = max (ans, pos);
	} //最长不下降子序列
	
	cout << ans << endl;
	return 0;
}

玄学

文件比较指令

cd\ //进入C盘
fc original_data.out output_data.out

快读

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

随机化

int true_random () {
	return int (1.0 * rand() / RAND_MAX * rand() + 0.5);
}//有点慢

mt19937 rand (time(0));
cout << rand() << endl; //编译环境:GNU C++11以上 (不一定能用)

模拟退火

inline void SimulateAnneal() {
	double t = 60000.0; //初始温度要大
	
	double nowx = ansx, nowy = ansy;
	while (t > 0.0001 && 1.0 * (clock() - fucking_time) / CLOCKS_PER_SEC < 0.7) { //最终温度要低,并且尽可能控制时间
		double nxtx = nowx + t * (true_rand() * 2 - 1), nxty = nowy + t * (true_rand() * 2 - 1); //在当前值附近随机
		double dlt = getval (nxtx, nxty) - getval (nowx, nowy);
		if (exp (-dlt / t) > true_rand()) { //以一定概率接受
			nowx = nxtx;
			nowy = nxty;
		}
		t *= 0.999; //慢慢降温
	}
	
	for (int i = 1; i <= 1000000 && 1.0 * (clock() - fucking_time) / CLOCKS_PER_SEC < 0.95; ++i) {
		double nxtx = ansx + t * (true_rand() * 2 - 1), nxty = ansy + t * (true_rand() * 2 - 1);
		getval (nxtx, nxty);
	} //再在最优值周围随机一会儿
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值