考前總結

大秦帝國發表於2020-11-06

考場常見模板

  1. 快讀優化

    inline void read(int &x)
    {
    	bool mark = false;
    	char ch = getchar();	
    	for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') mark = true;
    	for(x = 0; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
    	if(mark) x = -x;
    	return;
    }
    
  2. 尤拉函式計算

    int euler(int x)
    {
    	int res = x;
    	for(int i = 2; i <= sqrt(x); ++ i)
    	{
    		if(x % i == 0)
    		{
    			res = res / i * (i - 1);
    			while(x % i == 0) x /= i;
    		}
    		if(x == 1) return res;
    	}
    	if(x > 1) res = res / x * (x - 1);
    	return res;
    }
    
  3. 線性篩素數

    void primes()
    {
    	p.clear();
    	memset(vis, 0, sizeof(vis));
    	for(int i = 2; i <= n; ++ i)
    	{
    		if(!vis[i])
    		{
    			vis[i] = i;
    			p.push_back(i);
    		}
    		for(int j = 0; j < p.size(); ++ j)
    		{
    			if(p[j] > vis[i] || 1ll * p[j] * i > n) break;
    			vis[p[j] * i] = vis[i];
    		}
    	}
    	return;
    }
    
  4. 最大公因數(歐幾里得演算法)

    int gcd(int x, int y)
    {
        return y ? gcd(y, x % y) : x;
    }
    
  5. 擴充套件歐幾里得演算法(逆元:同餘方程)

    void exgcd(int a, int b, int &d, int &x, int &y)
    {
    	if(!b) d = a, x = 1, y = 0;
    	else
    	{
    		exgcd(b, a % b, d, y, x);
    		y -= x * (a / b);
    	}
    	return;
    }
    
  6. 快速冪(逆元:費馬小定理)

    int power(int x, int y, int k)
    {
    	int res = 1 % k;
    	while(y)
    	{
    		if(y & 1) res = 1ll * res * x % k;
    		y >>= 1;
    		x = 1ll * x * x % k;
    	}
    	return res;
    }
    
  7. 樹狀陣列

    #define lowbit(x) x&(-x)
    void add(int x, int v)
    {
    	while(x <= n)
    	{
    		c[x] += v;
    		x += lowbit(x);
    	}
    	return;
    }
    int ask(int x)
    {
    	int res = 0;
    	while(x)
    	{
    		res += c[x]; 
    		x -= lowbit(x);
    	}
    	return res;
    }
    
  8. 線段樹

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define lson p<<1,l,mid
    #define rson p<<1|1,mid+1,r
    #define wht 1,1,n
    struct Segment
    {
    	long long sum, flag;
    	inline void init(int v)
    	{
    		sum = v, flag = 0;
    		return;
    	}
    	inline void merge(struct Segment x, struct Segment y)
    	{
    		sum = x.sum + y.sum; 
    		return;
    	}	
    } T[N << 2];
    void spread(int p, int l, int r)
    {
    	if(l != r && T[p].flag)
    	{
    		int mid = l + ((r - l) >> 1);
    		T[p << 1].flag += T[p].flag;
    		T[p << 1].sum += (mid - l + 1) * T[p].flag;
    		T[p << 1 | 1].flag += T[p].flag;
    		T[p << 1 | 1].sum += (r - mid) * T[p].flag;
    	}
    	T[p].flag = 0;
    	return;
    }
    void build(int p, int l, int r)
    {
    	if(l == r)
    	{
    		int v;
    		read(v);
    		T[p].init(v);
    		return;
    	}
    	int mid = l + ((r - l) >> 1);
    	build(lson), build(rson);
    	T[p].merge(T[p << 1], T[p << 1 | 1]);
    }
    void modify(int p, int l, int r, int x, int v)
    {
    	spread(p, l, r);
    	if(l == r)
    	{
    		T[p].sum += v;
    		return;
    	}
    	int mid = l + ((r - l) >> 1);
    	if(x <= mid) modify(lson, x, v);
    	else modify(rson, x, v);
    	T[p].merge(T[p << 1], T[p << 1 | 1]);
    	return;
    }
    void modify(int p, int l, int r, int L, int R, int v)
    {
    	if(l >= L && r <= R) 
    	{
    		T[p].flag += v;
    		T[p].sum += 1ll * (r - l + 1) * v;
    		return;
    	}
    	spread(p, l, r);
    	int mid = l + ((r - l) >> 1);
    	if(L <= mid) modify(lson, L, R, v);
    	if(R > mid) modify(rson, L, R, v);
    	T[p].merge(T[p << 1], T[p << 1 | 1]);
    	return;
    }
    long long query(int p, int l, int r, int L, int R)
    {
    	if(l > R || r < L) return 0;
    	if(l >= L && r <= R)
    	{
    		return T[p].sum;
    	}
    	int mid = l + ((r - l) >> 1);
    	spread(p, l, r);
    	long long val = 0;
    	if(L <= mid) val = query(lson, L, R);
    	if(R > mid) val += query(rson, L, R);
    	return val;
    }
    
  9. 單調棧

    int t = 0;
    	for(int i = 1; i <= n; ++ i)
    	{
    		if(!t || a[s[t - 1]] >= a[i]) s[t ++] = i;
    		else
    		{
    			while(t && a[s[t - 1]] < a[i])
    			{
    				f[s[t - 1]] = i;
    				-- t;
    			}	
    			s[t ++] = i;
    		}
    	}
    
  10. 單調佇列(太基本了)

  11. 旅行商問題(TSP)

    dp[0][1] = 0;
    	for(int S = 2; S < 1 << n; ++ S)
    	{
    		for(int i = 0; i < n; ++ i)
    		{
    			if((1 << i) & S)
    			{
    				int pre_state = S ^ (1 << i);
    				for(int j = 0; j < n; ++ j)
    				{
    					if((1 << j) & pre_state)	
    					{
    						dp[i][S] = min(dp[i][S], dp[j][pre_state] + a[j][i]);
    					}
    				}				
    			}			
    		}
    	}
    
  12. Floyd

    for(int k = 1; k <= n; ++ k)
    		for(int i = 1; i <= n; ++ i)
    			for(int j = 1; j <= n; ++ j) 
    				dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]); 
    
  13. Dijkstra

    void Dijkstra(int S)
    {
    	while(Q.size()) Q.pop();
    	memset(vis, false, sizeof(vis));
    	memset(dis, 0x3f, sizeof(dis));
    	Q.push(make_pair(0, S));
    	dis[S] = 0;
    	while(Q.size())
    	{
    		int u = Q.top().second; Q.pop();
    		if(vis[u]) continue;
    		vis[u] = true;
    		for(int i = 0; i < G[u].size(); ++ i)
    		{
    			int v = G[u][i], w = W[u][i];
    			if(dis[v] > dis[u] + w)
    			{
    				dis[v] = dis[u] + w;
    				Q.push(make_pair(-dis[v], v));
    			}
    		 } 
    	}
    	return;
    }
    
  14. SPFA

    void Bellman_Ford()
    {
    	while(Q.size()) Q.pop();
    	memset(inq, false, sizeof(inq));
    	for(int i = 1; i <= n; ++ i) dis[i] = INF;
    	Q.push(s);
    	dis[s] = 0;
    	inq[s] = true;
    	while(Q.size())
    	{
    		int u = Q.front();
    		Q.pop();
    		inq[u] = false; 
    		for(int i = 0; i < G[u].size(); ++ i)
    		{
    			int v = G[u][i], w = W[u][i];
    			if(dis[v] > dis[u] + w)		
    			{
    				dis[v] = dis[u] + w;
    				if(!inq[v]) Q.push(v), inq[v] = true;
    			}
    		}
    	}
    	return;
    }
    

    SPFA求負環

    bool spfa()
    {
    	while(Q.size()) Q.pop();
    	memset(inq, false, sizeof(inq));
    	memset(dis, 0x3f, sizeof(dis));
    	memset(cnt, 0, sizeof(cnt));
    	dis[1] = 0;
    	inq[1] = true;
    	Q.push(1);
    	while(Q.size())
    	{
    		int u = Q.front(); Q.pop(); 
    		inq[u] = false;
    		for(int i = 0; i < G[u].size(); ++ i)
    		{
    			int v = G[u][i], w = W[u][i];
    			if(dis[v] > dis[u] + w)
    			{
    				dis[v] = dis[u] + w;
    				cnt[v] = cnt[u] + 1;
    				if(cnt[v] >= n) return true;
    				if(!inq[v]) Q.push(v), inq[v] = true;
    			}
    		}	
    	}
    	return false;
    }
    
  15. ST演算法

    void ST_prework()
    {
    	int t = log(n) / log(2);
    	for(int j = 1; j <= t; ++ j)
    	{
    		for(int i = 1; i <= n - (1 << j) + 1; ++ i)
    		{
    			f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
    		}
    	}
    	return;
    }
    int k = log(r - l + 1) / log(2);
    printf("%d\n", max(f[l][k], f[r - (1 << k) + 1][k]));
    
  16. 最近公共祖先(樹上倍增)

    void BFS()
    {
    	while(Q.size()) Q.pop();
    	memset(dep, 0, sizeof(dep));
    	Q.push(s);
    	dep[s] = 1; 
    	while(Q.size())
    	{
    		int u = Q.front();
    		Q.pop();
    		for(int i = 0; i < G[u].size(); ++ i)
    		{
    			int v = G[u][i];
    			if(dep[v]) continue;
    			dep[v] = dep[u] + 1;
    			F[v][0] = u;
    			for(int i = 1; i <= t; ++ i) F[v][i] = F[F[v][i - 1]][i - 1];
    			Q.push(v);
     		}
    	}
    	return;	
    }
    int LCA(int x, int y)
    {
    	if(dep[x] > dep[y]) swap(x, y);
    	for(int i = t; i >= 0; -- i) 
    	{
    		if(dep[F[y][i]] >= dep[x]) 
    		{
    			y = F[y][i]; 
    		} 
    	} 
    	if(x == y) return x;
    	for(int i = t; i >= 0; -- i)
    	{
    		if(F[x][i] != F[y][i])
    		{
    			x = F[x][i]; 
    			y = F[y][i];
    		}	
    	}
    	return F[x][0];
    }
    
  17. Topsort

    void Topsort()
    {
        while(Q.size()) Q.pop();
        for(int i = 1; i <= n; ++ i) if(!deg[i]) Q.push(i);
        while(Q.size())
        {
            int u = Q.front(); 
            Q.pop();
        for(int i = 0; i < G[u].size(); ++ i)
        {
    		int v = G[u][i];            
             -- deg[v];
            if(!deg[v]) Q.push(v);
        }
    }
    return;
    }
    
  18. Kruskal

    struct edge
    {
    	int u, v, w;
    	inline bool operator <(const edge& lhs) const
    	{
    		return w < lhs.w;	
    	}	
    } e[M];
    int get(int x)
    {
    	if(x == fa[x]) return x;
    	return fa[x] = get(fa[x]);
    }
    int main()
    {
    	sort(e, e + m);
    	for(int i = 0; i < m; ++ i)
    	{
    		int u = e[i].u, v = e[i].v, v1 = get(u), v2 = get(v);
    		if(v1 == v2) continue;
    		fa[v1] = v2;
    		ans += e[i].w;
    	}
    	return 0; 
     }