Noip2018 考前准备

未完成先看吧.大概9.1号完成.
然而现在都8102年了...

基础算法

二分

求最小值最大.
跳石头

#include <iostream>
#include <cstdio>
using namespace std;
const int maxN = 50000 + 7;

int a[maxN],n,m;
int L;

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

bool calc(int k) {
    int num = 0,path = 0;
    for(int i = 1;i <= n;++ i) {
        if(a[i] - a[path] < k) { 
            num ++;
        }else path = i;
    }
    return num <= m;
}

int main() {
    L = read();n = read();m = read();
    for(int i = 1;i <= n;++ i) a[i] = read();
    n ++;
    a[n] = L;
    int l = 0,r = L,ans;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(calc(mid)) {
            ans = mid;
            l = mid + 1;
        }
        else r = mid - 1;
    }
    printf("%d",ans);
    return 0;
}

模拟(未补)

高精(未学习)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<string>
using namespace std;



struct bignum
{
    int n;
    int a[500];
    bignum()
    {
        n = 0;
        memset(a, 0, sizeof(a));
    }
        
    bignum(string s)
    {
        n = s.size();
        memset(a, 0, sizeof(a));
        for (int i = 0; i < n; i++)
            a[i] = s[n - 1 -i] -'0';
    }
    bignum(int s)
    {
        memset(a, 0, sizeof(a));
        n = 0;
        while (s > 0)
        {
            a[n] = s % 10;
            s /= 10;
            n++;
        }
    }
    void work()
    {
        for (int i = 0; i < n; i++)
        {
            if (a[i] < 0)
            {
                int tmp = (-a[i] - 1) / 10 + 1;
                a[i] += 10 * tmp;
                a[i + 1] -= tmp;
            }
            if (a[i] >= 10)
            {
                int tmp = a[i] / 10;
                a[i] -= 10* tmp;
                a[i + 1] += tmp;
                if (i == n - 1 && a[i + 1] > 0) n++;
            }
        }
        while (n > 0 && a[n - 1] == 0) n--;
    }
    void print()
    {
        for (int i = n - 1; i >= 0; i--)
            cout << a[i];
        cout << endl;
    }
};

bignum operator + (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = max(a.n, b.n);
    for (int i = 0; i < c.n; i++)
        c.a[i] = a.a[i] + b.a[i];
    c.work();
    return c;
}


bignum operator - (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = max(a.n, b.n);
    for (int i = 0; i < c.n; i++)
        c.a[i] = a.a[i] - b.a[i];
    c.work();
    return c;
}


bignum operator * (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = a.n + b.n - 1;
    for (int i = 0; i < a.n; i++)
        for (int j = 0; j < b.n; j++)
            c.a[i + j] += a.a[i] * b.a[j];
    c.work();
    return c;
}


int main()
{
    string s;
    cin >> s;
    int x;
    cin >> x;
    bignum a(s);
    bignum b(x);
    (a + b).print();
    (a - b).print();
    (a * b).print();
    return 0;
}

搜索(未补)

排序

merge_sort(归并排序)

#include <iostream>
#include <cstdio>
const int maxN = 100000 + 7;

int z[maxN],a[maxN];

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

void merge(int l,int r) {
	if(l == r) return;
	int mid = l + r >> 1;
	merge(l,mid);
	merge(mid + 1,r);
	int z1 = l,z2 = mid + 1;
	for(int i = l;i <= r;++ i) {
		if(z1 <= mid) 
			if(z2 <= r) 
				if(a[z1] >= a[z2]) z[i] = a[z2 ++];
				else z[i] = a[z1 ++];
			else z[i] = a[z1 ++];
		else z[i] = a[z2 ++];
	}
	for(int i = l;i <= r;++ i) 
		a[i] = z[i];
}
 
int main() {
	int n = read();
	for(int i = 1;i <= n;++ i) 
		a[i] = read();
	merge(1,n);
	for(int i = 1;i <= n;++ i) 
		printf("%d ",a[i]);
	return 0;
}

图论

树的直径

POJ2631

#include <cstring>
#include <iostream>
#include <cstdio>
#include <vector>
const int maxN = 10000 + 7;
using namespace std;

int ans,id,n = 1;
int Rode[maxN];

struct Node{
	int v,w;
};

vector<Node>Q[maxN];

void dfs1(int now,int fa) {
	for(int i = 0;i < Q[now].size();++ i) {
		int v = Q[now][i].v,w = Q[now][i].w;
		if(v == fa) continue;
		Rode[v] = Rode[now] + w;
		dfs1(v,now);
	}
	return;
}

int max(int a,int b) {
	return a > b ? a : b ;
}

int main() {
	#ifdef WIN32
    freopen("a.txt","r",stdin);
    #endif
	int u,v,w;
	while(scanf("%d%d%d",&u,&v,&w) == 3) {
		Q[u].push_back((Node) {v,w});
		Q[v].push_back((Node) {u,w});
		n ++;
	}
	dfs1(1,-1);
	for(int i = 1;i <= n;++ i) {		
		if(ans < Rode[i]) {
			ans = Rode[i];
			id = i;
		}
	}
	memset(Rode,0,sizeof(Rode)); 
	dfs1(id,-1);
	ans = 0;
	for(int i = 1;i <= n;++ i)
		ans = max(ans,Rode[i]);
	printf("%d",ans);
	return 0;
}

树的重心

POJ1655

#include <iostream>
#include <cstdio>
#include <vector> 
const int maxN = 20000 + 7;
using namespace std;
 
vector<int> g[maxN];
int n;
int ans,id;

int max(int a,int b) {return a > b ? a : b;}
int min(int a,int b) {return a > b ? b : a;}

int dfs(int now,int fa) {
	int son = 1,maxson = 0,kkk;
	for(int i = 0;i < g[now].size();++ i) {
		int v = g[now][i];
		if(v == fa) continue;
		int Q = dfs(v,now);
		son += Q;
		maxson = max(maxson,Q);
	}
	kkk = max(maxson,n - son);
	if(kkk < ans) {
		ans = kkk;
		id = now;
	}
	return son;
}

int main() {
	int T;
	scanf("%d",&T);
	while(T --) {
		scanf("%d",&n);
		for(int i = 1;i <= n;++ i) 
			g[i].clear(); 
		for(int i = 1,u,v;i < n;++ i) {
			scanf("%d%d",&u,&v);
			g[u].push_back(v);
			g[v].push_back(u);
		}
		ans = 0x7fffffff;
		dfs(1,-1);
		printf("%d %d\n",id,ans);
	} 
	return 0;
}

最短路算法

题目单源最短路径(弱化版)

Spfa

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
const int maxN = 100000 + 7;
const int maxM = 200000 + 7;
const int inf = 2147483647;
using namespace std;

int dis[maxN];
bool vis[maxN];
int max(int a,int b) {return a > b ? a : b;}
int min(int a,int b) {return a > b ? b : a;}

struct Node{
	int v,w,nex;
}Map[maxM];

int head[maxN],num;

void add_Node(int u,int v,int w) {
	Map[++ num].v = v;
	Map[num].w = w;
	Map[num].nex = head[u];
	head[u] = num;
	return;
}

void spfa(int now) {
	queue<int>q;
	q.push(now);
	vis[now] = true;
	dis[now] = 0;
	while(!q.empty()) {
		int u = q.front();q.pop();
		vis[u] = 0; 
		for(int i = head[u];i != -1;i = Map[i].nex) {
			int v = Map[i].v;
			if(dis[v] > dis[u] + Map[i].w) {
				dis[v] = dis[u] + Map[i].w;
				if( !vis[v] ) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return ;
}

int main() {
	memset(dis,0x3f,sizeof(dis));
	memset(head,-1,sizeof(head));
	int n,m,s;
	scanf("%d%d%d",&n,&m,&s);
	for(int i = 1,u,v,w;i <= m;++ i) {
		scanf("%d%d%d",&u,&v,&w);
		add_Node(u,v,w);
	}
	spfa(s);
	for(int i = 1;i <= n;++ i) 
		printf("%d ",dis[i] == 0x3f3f3f3f ? inf : dis[i]);
	return 0;
}

Dijkstra

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int inf = 0x7fffffff;
const int maxN = 100000 + 7;
const int maxM = 200000 + 7;

struct Node{
	int x,y;
	inline bool operator < (const Node &a) const {
		return y > a.y;
	}
}; 
priority_queue<Node> q;
struct qode{
	int v,nex,w;
}Map[maxM];

int s,dis[maxN],n,m,num,head[maxN];

void add_Node(int u,int v,int w) {
	Map[++ num].v = v;
	Map[num].w = w;
	Map[num].nex = head[u];
	head[u] = num; 
}

void dij() {
	for(int i = 1;i <= n;++ i) dis[i] = inf;
	q.push((Node){s,0});
	dis[s] = 0;
	while(!q.empty()) {
		Node x = q.top();q.pop();
		if(x.y != dis[x.x]) continue;
		for(int i = head[x.x];i;i = Map[i].nex) {
			int v = Map[i].v;
			if(dis[v] > dis[x.x] + Map[i].w) {
				dis[v] = dis[x.x] + Map[i].w;
				q.push((Node){v,dis[v]});
			}
		}
	} 
	for(int i = 1;i <= n;++  i) {
		printf("%d ",dis[i]);
	}
}

int main() {
	scanf("%d%d%d",&n,&m,&s);
	for(int i = 1,u,v,w;i <= m;++ i) {
		scanf("%d%d%d",&u,&v,&w);
		add_Node(u,v,w);
	}	
	dij();
	return 0;
}

Floyd

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int a[101][101];
int main()  {
    int n,m,s;
    scanf("%d%d%d",&n,&m,&s);
    memset(a,0x3f,sizeof(a));
    for(int i = 1,u,v,w;i <= m;++ i) {
        scanf("%d%d%d",&u,&v,&w);
        a[u][v]=min(a[u][v],w);
    }
    for(int k = 1;k <= n;++ k) 
    	for(int i = 1;i <= n;++ i)
    		for(int j = 1;j <= n;++ j) 
    			a[i][j] = min(a[i][j],a[i][k] + a[k][j]);
    a[s][s] = 0;
    for(int i = 1;i <= n;++ i) {
        printf("%d ",a[s][i] == 0x3f3f3f3f ? 2147483647 : a[s][i]);
    }
}

最小生成树

kruskal

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxN = 5000 + 7;
const int maxM = 200000 + 7;

inline int read() {
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    return x * f;
}
struct Node {
    int u,v,w;
}Q[maxM];
int fa[maxN];

int find(int x) {
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

void un(int a,int b) {
    int faa = find(a),fab = find(b);
    fa[faa] = fab;
    return;
}

bool cmp(Node a,Node b) {
    return a.w < b.w;
}

int num = 0;
void add_Node(int u,int v,int w) {
    Q[++ num].u = u;
    Q[num].v = v;
    Q[num].w = w;
}

int main() {
    int n,m;
    n = read();m = read();
    for(int i = 1;i <= n;++ i) fa[i] = i;
    for(int i = 1,u,v,w;i <= m;++ i) {
        u = read();v = read();w = read();
        add_Node(u,v,w);
    }
    sort(Q + 1,Q + m + 1,cmp);
    int sum = 0,k = 0;
    for(int i = 1;i <= m;++ i) {
        int fau = find(Q[i].u),fav = find( Q[i].v);
        if(fau != fav) {
            k ++ ;
            sum += Q[i].w;
            un(fau,fav);
            if(k == n - 1) break;
        }
    }
    if(k == n - 1) printf("%d",sum);
    else printf("orz");
}

数论

线性筛

线性筛素数

void init1(int n) {
	vis[1] = 1;
	for(int i = 2;i <= n;++ i) {
		if(!vis[i]) prime[++ num] = i;
		for(int j = 1;prime[j] * i <= n;++ j) {
			vis[i * prime[j]] = true;
			if(i % prime[j] == 0) break;
		}
	}
} 

线性筛phi

int phi[maxN];
void init2(int n) {
	vis[1] = 1;
	phi[1] = 1;
	for(int i = 2;i <= n;++ i) {
		if( !vis[i] ) {
			prime[++ num] = i;
			phi[i] = i - 1;
		}
		for(int j = 1;j <= num && prime[j] * i <= n;++ j) {
			vis[i * prime[j]] = true;
			if(i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] =  phi[i] *( prime[j] - 1);
		}
	}	
}

线性筛莫比乌斯函数

int mu[maxN];
void init3(int n) {
	vis[1] = 1;
	mu[1] = 1;
	for(int i = 2;i <= n;++ i) {
		if(!vis[i]) {
			prime[++ num] = i;
			mu[i] = -1;
		}
		for(int j = 1;j <= num && prime[j] * i <= n;++ j) {
			vis[i * prime[j]] = true;
			if(i % prime[j] == 0) {
				mu[i * prime[j]] = 0;
				break;
			}
			mu[i * prime[j]] = -mu[i];
		}
	}
	return;
} 

gcd(最大公因数)

int gcd(int a,int b) {
	while(b ^= a ^= b ^= a %= b);
	return a;
}

lcm(最小公倍数)

int lcm(int a,int b) {
	return a / gcd(a,b) * b;
}

快速幂

int fast_pow(int a,int b,int k) {
	int ans = 1;
	for(int now = a;b;b >>= 1,now = now * now) {
		now %= k;
		if(b & 1) ans *= now;
		ans %= k;
	}
	return ans % k;
}

扩展欧几里得算法

void exgcd(int a,int b,int &x,int &y) {
	if( !b ) {
		x = 1;
		y = 0;
		return;
	}
	exgcd(b,a % b,x,y);
	int tmp = x;
	x = y;
	y = tmp - (a / b) * y;
	return;
}

逆元

nt inv(int n,int p) {
	for(int i = 1,x,y;i <= n;++ i) {
		exgcd(i,p,x,y);
		printf("%d\n",(x % p + p) % p);
	}
} //a * x ≡ q (mod p)

矩阵快速幂


ll n,m,k;
struct Marix{
	ll s[107][107];
	void clear() {
		memset(s,0,sizeof(s));
		return;
	}
}ans,now,a;

Marix work(Marix a,Marix b) {
	Marix c;
	c.clear();
	for(ll i = 1;i <= n;++ i) 
		for(ll j = 1;j <= n;++ j) 
			for(ll k = 1;k <= n;++ k) 
				c.s[i][j] = ( c.s[i][j]  % mod+ ( a.s[i][k] * b.s[k][j] ) % mod ) % mod;
	return c;
}

void fast_pow() {
	ans.clear();
	for(ll i = 1;i <= n;++ i) {
		ans.s[i][i] = 1;
	}
	for(now = a;k;k >>= 1,now = work(now,now)) {
		if(k & 1) ans = work(ans,now);
	}
	for(ll i = 1;i <= n;++ i) {
		for(ll j = 1;j <= n;++ j) {
			printf("%lld ",ans.s[i][j]);
		}
		puts("");
	}
}
void Marix_fast_power() {
	scanf("%lld%lld",&n,&k);
	for(int i = 1;i <= n;++ i) {
		for(int j = 1;j <= n;++ j) {
			scanf("%lld",&a.s[i][j]);
		}
	}
	fast_pow();
	return ;
}

数据结构

ST表

#include <iostream>
#include <cstdio>
#define max(a,b) a > b ? a : b
#define min(a,b) a > b ? b : a
const int maxN = 1e5 + 7; 
using namespace std;
int f[maxN][21];
int a[maxN];
int bin[maxN];
int n,m;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}

void build_st() {
	for(int i = 1;(1 << i) <= n;++ i) 
		bin[(1 << i)] = i;
	for(int i = 3;i <= n;++ i)
		if(!bin[i]) bin[i] = bin[i - 1];
	for(int i = 1;i <= n;++ i) 
		f[i][0] = a[i];
	for(int j = 1;(1 << j) <= n;++ j) {
		for(int i = 1;i + (1 << j) - 1 <= n;++ i) {
			f[i][j] = max(f[i + (1 << (j - 1))][j - 1],f[i][j - 1]);
		} 
	}
}

int query(int l,int r) {
	int x = bin[r - l + 1];
	return max(f[l][x],f[r - (1 << x) + 1][x]); 
}
int main() {
	n = read();m = read();
	for(int i = 1;i <= n;++ i) 
		a[i] = read();
	build_st();
	int l,r;
	while(m --) {
		l = read();r = read();
		printf("%d\n",query(l,r));
	}	
	return 0;
}

并查集

#include <iostream>
#include <cstdio>
using namespace std;
const int maxN = 10000 + 7;

int fa[maxN];

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

int find(int x) {
	return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}

void unit(int u,int v) {
	int fau = find(u),fav = find(v);
	fa[fau] = fav;
	return;
}

int main() {
	int n,m;
	n = read();m = read();
	for(int i = 1;i <= 10000;++ i) 
		fa[i] = i;
	int opt,u,v;
	while(m -- ) {
		opt = read();u = read();v = read();
		if(opt & 1) unit(u,v);
		else {
			int fau = find(u),fav = find(v);
			if(fau == fav) printf("Y\n");
			else printf("N\n");
		}
	}
}
posted @ 2018-08-09 21:21  Rlif  阅读(262)  评论(2编辑  收藏  举报