码迷,mamicode.com
首页 > 其他好文 > 详细

【冲刺noi】真banzi大集合

时间:2017-07-16 12:36:09      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:数据   可并堆   高斯消元   dinic   fail   区间修改   rmi   wap   倍增lca   

自己风格的板子 = =

考试时别把板子码错就好 = =

一、数据结构

1.树状数组单点修改区间查询(luogu3374)

#include <cstdio>
int f[500010] , n;
void add(int x , int a)
{
	int i;
	for(i = x ; i <= n ; i += i & -i) f[i] += a;
}
int query(int x)
{
	int i , ans = 0;
	for(i = x ; i ; i -= i & -i) ans += f[i];
	return ans;
}
int main()
{
	int m , i , opt , x , y;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , add(i , x);
	for(i = 1 ; i <= m ; i ++ )
	{
		scanf("%d%d%d" , &opt , &x , &y);
		if(opt == 1) add(x , y);
		else printf("%d\n" , query(y) - query(x - 1));
	}
	return 0;
}

2.树状数组区间修改区间查询(luogu3372)

#include <cstdio>
typedef long long ll;
int n;
struct data
{
	ll f[100010];
	void add(int x , ll a)
	{
		int i;
		for(i = x ; i <= n ; i += i & -i) f[i] += a;
	}
	ll query(int x)
	{
		int i;
		ll ans = 0;
		for(i = x ; i ; i -= i & -i) ans += f[i];
		return ans;
	}
}A , B;
void modify(int p , ll a)
{
	A.add(p , a) , B.add(p , a * p);
}
ll solve(int p)
{
	return (p + 1) * A.query(p) - B.query(p);
}
int main()
{
	int m , i , opt , x , y;
	ll z;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &z) , modify(i , z) , modify(i + 1 , -z);
	for(i = 1 ; i <= m ; i ++ )
	{
		scanf("%d%d%d" , &opt , &x , &y);
		if(opt == 1) scanf("%lld" , &z) , modify(x , z) , modify(y + 1 , -z);
		else printf("%lld\n" , solve(y) - solve(x - 1));
	}
	return 0;
}

3.线段树区间修改区间查询(luogu3373)

#include <cstdio>
#include <algorithm>
#define N 400010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
ll p , sum[N] , mul[N] , add[N];
void pushup(int x)
{
	sum[x] = (sum[x << 1] + sum[x << 1 | 1]) % p;
}
void pushdown(int l , int r , int x)
{
	int ls = x << 1 , rs = x << 1 | 1 , mid = (l + r) >> 1;
	if(mul[x] != 1)
	{
		sum[ls] = sum[ls] * mul[x] % p , mul[ls] = mul[ls] * mul[x] % p , add[ls] = add[ls] * mul[x] % p;
		sum[rs] = sum[rs] * mul[x] % p , mul[rs] = mul[rs] * mul[x] % p , add[rs] = add[rs] * mul[x] % p;
		mul[x] = 1;
	}
	if(add[x])
	{
		sum[ls] = (sum[ls] + add[x] * (mid - l + 1)) % p , add[ls] = (add[ls] + add[x]) % p;
		sum[rs] = (sum[rs] + add[x] * (r - mid)) % p , add[rs] = (add[rs] + add[x]) % p;
		add[x] = 0;
	}
}
void build(int l , int r , int x)
{
	mul[x] = 1 , add[x] = 0;
	if(l == r)
	{
		scanf("%lld" , &sum[x]);
		return;
	}
	int mid = (l + r) >> 1;
	build(lson) , build(rson);
	pushup(x);
}
void updatemul(int b , int e , ll m , int l , int r , int x)
{
	if(b <= l && r <= e)
	{
		sum[x] = sum[x] * m % p , mul[x] = mul[x] * m % p , add[x] = add[x] * m % p;
		return;
	}
	pushdown(l , r , x);
	int mid = (l + r) >> 1;
	if(b <= mid) updatemul(b , e , m , lson);
	if(e > mid) updatemul(b , e , m , rson);
	pushup(x);
}
void updateadd(int b , int e , ll a , int l , int r , int x)
{
	if(b <= l && r <= e)
	{
		sum[x] = (sum[x] + a * (r - l + 1)) % p , add[x] = (add[x] + a) % p;
		return;
	}
	pushdown(l , r , x);
	int mid = (l + r) >> 1;
	if(b <= mid) updateadd(b , e , a , lson);
	if(e > mid) updateadd(b , e , a , rson);
	pushup(x);
}
ll query(int b , int e , int l , int r , int x)
{
	if(b <= l && r <= e) return sum[x];
	pushdown(l , r , x);
	int mid = (l + r) >> 1;
	ll ans = 0;
	if(b <= mid) ans += query(b , e , lson);
	if(e > mid) ans += query(b , e , rson);
	return ans % p;
}
int main()
{
	int n , m , i , opt , x , y;
	ll z;
	scanf("%d%d%lld" , &n , &m , &p);
	build(1 , n , 1);
	for(i = 1 ; i <= m ; i ++ )
	{
		scanf("%d%d%d" , &opt , &x , &y);
		if(opt == 1) scanf("%lld" , &z) , updatemul(x , y , z , 1 , n , 1);
		else if(opt == 2) scanf("%lld" , &z) , updateadd(x , y , z , 1 , n , 1);
		else printf("%lld\n" , query(x , y , 1 , n , 1));
	}
	return 0;
}

4.Treap(loj104)

#include <cstdio>
#include <cstdlib>
#define N 100010
int l[N] , r[N] , w[N] , si[N] , cnt[N] , rnd[N] , tot , root , tmp;
void zig(int &k)
{
	int t = l[k];
	l[k] = r[t] , r[t] = k , si[t] = si[k] , si[k] = si[l[k]] + si[r[k]] + cnt[k] , k = t;
}
void zag(int &k)
{
	int t = r[k];
	r[k] = l[t] , l[t] = k , si[t] = si[k] , si[k] = si[l[k]] + si[r[k]] + cnt[k] , k = t;
}
void insert(int &k , int x)
{
	if(!k) k = ++tot , w[k] = x , si[k] = cnt[k] = 1 , rnd[k] = rand();
	else if(x == w[k]) si[k] ++ , cnt[k] ++ ;
	else if(x < w[k])
	{
		si[k] ++ , insert(l[k] , x);
		if(rnd[l[k]] < rnd[k]) zig(k);
	}
	else
	{
		si[k] ++ , insert(r[k] , x);
		if(rnd[r[k]] < rnd[k]) zag(k);
	}
}
void del(int &k , int x)
{
	if(x == w[k])
	{
		if(cnt[k] > 1) si[k] -- , cnt[k] -- ;
		else if(!l[k] || !r[k]) k = l[k] + r[k];
		else if(rnd[l[k]] < rnd[r[k]]) zig(k) , del(k , x);
		else zag(k) , del(k , x);
	}
	else if(x < w[k]) si[k] -- , del(l[k] , x);
	else si[k] -- , del(r[k] , x);
}
int getrank(int k , int x)
{
	if(x < w[k]) return getrank(l[k] , x);
	else if(x > w[k]) return getrank(r[k] , x) + si[l[k]] + cnt[k];
	else return si[l[k]] + 1; 
}
int find(int k , int x)
{
	if(x <= si[l[k]]) return find(l[k] , x);
	else if(x > si[l[k]] + cnt[k]) return find(r[k] , x - si[l[k]] - cnt[k]);
	else return w[k];
}
void pro(int k , int x)
{
	if(!k) return;
	else if(w[k] < x) tmp = w[k] , pro(r[k] , x);
	else pro(l[k] , x);
}
void sub(int k , int x)
{
	if(!k) return;
	else if(w[k] > x) tmp = w[k] , sub(l[k] , x);
	else sub(r[k] , x);
}
int main()
{
	int n , opt , x;
	scanf("%d" , &n);
	while(n -- )
	{
		scanf("%d%d" , &opt , &x);
		switch(opt)
		{
			case 1: insert(root , x); break;
			case 2: del(root , x); break;
			case 3: printf("%d\n" , getrank(root , x)); break;
			case 4: printf("%d\n" , find(root , x)); break;
			case 5: pro(root , x); printf("%d\n" , tmp); break;
			default: sub(root , x); printf("%d\n" , tmp); break;
		}
	}
	return 0;
}

5.Splay(loj105)

#include <cstdio>
#include <algorithm>
#define N 100010
using namespace std;
int fa[N] , c[2][N] , si[N] , rev[N] , root;
void rever(int x)
{
	swap(c[0][x] , c[1][x]) , rev[x] ^= 1;
}
void pushup(int x)
{
	si[x] = si[c[0][x]] + si[c[1][x]] + 1;
}
void pushdown(int x)
{
	if(rev[x]) rever(c[0][x]) , rever(c[1][x]) , rev[x] = 0;
}
void build(int l , int r , int f)
{
	if(l > r) return;
	int mid = (l + r) >> 1;
	build(l , mid - 1 , mid) , build(mid + 1 , r , mid);
	fa[mid] = f , c[mid > f][f] = mid;
	pushup(mid);
}
void rotate(int &k , int x)
{
	int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
	if(y == k) k = x;
	else c[c[1][z] == y][z] = x;
	fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
	pushup(y) , pushup(x);
}
void splay(int &k , int x)
{
	while(x != k)
	{
		int y = fa[x] , z = fa[y];
		if(y != k)
		{
			if((c[0][y] == x) ^ (c[0][z] == y)) rotate(k , x);
			else rotate(k , y);
		}
		rotate(k , x);
	}
}
int find(int k , int x)
{
	pushdown(k);
	if(x <= si[c[0][k]]) return find(c[0][k] , x);
	else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
	else return k;
}
int split(int l , int r)
{
	int a = find(root , l) , b = find(root , r + 2);
	splay(root , a) , splay(c[1][root] , b);
	return c[0][c[1][root]];
}
int main()
{
	int n , m , i , x , y;
	scanf("%d%d" , &n , &m);
	build(1 , n + 2 , 0) , root = (n + 3) >> 1;
	while(m -- ) scanf("%d%d" , &x , &y) , rever(split(x , y));
	for(i = 2 ; i <= n + 1 ; i ++ ) printf("%d " , find(root , i) - 1);
	return 0;
}

6.主席树查询区间排名(loj106)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
int w[N] , opt[N] , x[N] , y[N] , z[N] , v[N] , num , c , root[N] , ls[N * 105] , rs[N * 105] , si[N * 105] , tot , R[20] , L[20] , cr , cl;
void update(int p , int a , int l , int r , int x , int &y)
{
	y = ++tot , si[y] = si[x] + a;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(p <= mid) rs[y] = rs[x] , update(p , a , l , mid , ls[x] , ls[y]);
	else ls[y] = ls[x] , update(p , a , mid + 1 , r , rs[x] , rs[y]);
}
int getrank(int p , int l , int r)
{
	if(l == r) return 1;
	int mid = (l + r) >> 1 , i , sum = 0;
	if(p <= mid)
	{
		for(i = 1 ; i <= cr ; i ++ ) R[i] = ls[R[i]];
		for(i = 1 ; i <= cl ; i ++ ) L[i] = ls[L[i]];
		return getrank(p , l , mid);
	}
	else
	{
		for(i = 1 ; i <= cr ; i ++ ) sum += si[ls[R[i]]] , R[i] = rs[R[i]];
		for(i = 1 ; i <= cl ; i ++ ) sum -= si[ls[L[i]]] , L[i] = rs[L[i]];
		return getrank(p , mid + 1 , r) + sum;
	}
}
int find(int k , int l , int r)
{
	if(l == r) return v[l];
	int mid = (l + r) >> 1 , i , sum = 0;
	for(i = 1 ; i <= cr ; i ++ ) sum += si[ls[R[i]]];
	for(i = 1 ; i <= cl ; i ++ ) sum -= si[ls[L[i]]];
	if(k <= sum)
	{
		for(i = 1 ; i <= cr ; i ++ ) R[i] = ls[R[i]];
		for(i = 1 ; i <= cl ; i ++ ) L[i] = ls[L[i]];
		return find(k , l , mid);
	}
	else
	{
		for(i = 1 ; i <= cr ; i ++ ) R[i] = rs[R[i]];
		for(i = 1 ; i <= cl ; i ++ ) L[i] = rs[L[i]];
		return find(k - sum , mid + 1 , r);
	}
}
void init(int x , int y)
{
	int i;
	for(cr = 0 , i = y ; i ; i -= i & -i) R[++cr] = root[i];
	for(cl = 0 , i = x - 1 ; i ; i -= i & -i ) L[++cl] = root[i];
}
int main()
{
	int n , m , i , j , t;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &w[i]) , v[++num] = w[i];
	for(i = 1 ; i <= m ; i ++ )
	{
		scanf("%d%d" , &opt[i] , &x[i]);
		if(opt[i] != 3) scanf("%d" , &y[i]);
		scanf("%d" , &z[i]);
		if(opt[i] != 2) v[++num] = z[i];
	}
	sort(v + 1 , v + num + 1) , v[0] = -1 << 30;
	for(i = 1 ; i <= num ; i ++ ) if(v[i] != v[i - 1]) v[++c] = v[i];
	for(i = 1 ; i <= n ; i ++ ) w[i] = lower_bound(v + 1 , v + c + 1 , w[i]) - v;
	for(i = 1 ; i <= m ; i ++ )
		if(opt[i] != 2)
			z[i] = lower_bound(v + 1 , v + c + 1 , z[i]) - v;
	for(i = 1 ; i <= n ; i ++ )
		for(j = i ; j <= n ; j += j & -j)
			update(w[i] , 1 , 1 , c , root[j] , root[j]);
	for(i = 1 ; i <= m ; i ++ )
	{
		if(opt[i] != 3) init(x[i] , y[i]);
		switch(opt[i])
		{
			case 1: printf("%d\n" , getrank(z[i] , 1 , c)); break;
			case 2: printf("%d\n" , find(z[i] , 1 , c)); break;
			case 3: for(j = x[i] ; j <= n ; j += j & -j) update(w[x[i]] , -1 , 1 , c , root[j] , root[j]) , update(z[i] , 1 , 1 , c , root[j] , root[j]); w[x[i]] = z[i]; break;
			case 4: t = getrank(z[i] , 1 , c) , init(x[i] , y[i]) , printf("%d\n" , find(t - 1 , 1 , c)); break;
			default: t = getrank(z[i] + 1 , 1 , c) , init(x[i] , y[i]) , printf("%d\n" , find(t , 1 , c));
		}
	}
	return 0;
}

7.可持久化线段树查询平面矩形内点数(bzoj4826)

#include <cstdio>
#include <algorithm>
#define N 200010
#define lson l , mid , ls[x] , ls[y]
#define rson mid + 1 , r , rs[x] , rs[y]
using namespace std;
typedef long long ll;
struct data
{
    int x , l , r;
    ll p;
    data() {}
    data(int x0 , int l0 , int r0 , ll p0) {x = x0 , l = l0 , r = r0 , p = p0;}
}v[N << 2];
int a[N] , lp[N] , rp[N] , sta[N] , top , cnt , root[N] , ls[N << 6] , rs[N << 6] , tot;
ll sum[N << 6] , add[N << 6];
bool cmp(data a , data b)
{
    return a.x < b.x;
}
void pushup(int x)
{
    sum[x] = sum[ls[x]] + sum[rs[x]];
}
void insert(int b , int e , ll a , int l , int r , int x , int &y)
{
    y = ++tot , ls[y] = ls[x] , rs[y] = rs[x] , add[y] = add[x] , sum[y] = sum[x] + a * (e - b + 1);
    if(b == l && r == e)
    {
        add[y] += a;
        return;
    }
    int mid = (l + r) >> 1;
    if(e <= mid) insert(b , e , a , lson);
    else if(b > mid) insert(b , e , a , rson);
    else insert(b , mid , a , lson) , insert(mid + 1 , e , a , rson);
}
ll query(int b , int e , int l , int r , int x , int y)
{
    if(b <= l && r <= e) return sum[y] - sum[x];
    int mid = (l + r) >> 1;
    ll ans = (add[y] - add[x]) * (e - b + 1);
    if(e <= mid) return ans + query(b , e , lson);
    else if(b > mid) return ans + query(b , e , rson);
    else return ans + query(b , mid , lson) + query(mid + 1 , e , rson);
}
int main()
{
    int n , m , i , j , x , y;
    ll p1 , p2;
    scanf("%d%d%lld%lld" , &n , &m , &p1 , &p2);
    for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
    a[0] = a[n + 1] = 1 << 30 , top = 1;
    for(i = 1 ; i <= n ; i ++ )
    {
        while(a[sta[top]] < a[i]) top -- ;
        lp[i] = sta[top] , sta[++top] = i;
    }
    top = 1 , sta[1] = n + 1;
    for(i = n ; i >= 1 ; i -- )
    {
        while(a[sta[top]] < a[i]) top -- ;
        rp[i] = sta[top] , sta[++top] = i;
    }
    for(i = 1 ; i <= n ; i ++ )
    {
        if(lp[i] != 0 && rp[i] != n + 1) v[++cnt] = data(lp[i] , rp[i] , rp[i] , p1);
        if(i < n) v[++cnt] = data(i , i + 1 , i + 1 , p1);
        if(lp[i] != 0 && rp[i] - i > 1) v[++cnt] = data(lp[i] , i + 1 , rp[i] - 1 , p2);
        if(rp[i] != n + 1 && i - lp[i] > 1) v[++cnt] = data(rp[i] , lp[i] + 1 , i - 1 , p2);
    }
    sort(v + 1 , v + cnt + 1 , cmp);
    for(i = j = 1 ; i <= n ; i ++ )
    {
        root[i] = root[i - 1];
        while(j <= cnt && v[j].x == i)
            insert(v[j].l , v[j].r , v[j].p , 1 , n , root[i] , root[i]) , j ++ ;
    }
    while(m -- )
    {
        scanf("%d%d" , &x , &y);
        printf("%lld\n" , query(x , y , 1 , n , root[x - 1] , root[y]));
    }
    return 0;
}

8.并查集(loj109)

#include <cstdio>
int f[4000010];
int find(int x)
{
	return x == f[x] ? x : f[x] = find(f[x]);
}
int main()
{
	int n , m , i , opt , x , y , ans = 0;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= n ; i ++ ) f[i] = i;
	for(i = 1 ; i <= m ; i ++ )
	{
		scanf("%d%d%d" , &opt , &x , &y);
		if(opt) ans = (ans * 2 + (find(x) == find(y))) % 998244353;
		else f[find(x)] = find(y);
	}
	printf("%d\n" , ans);
	return 0;
}

9.分块(bzoj4241)

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
typedef long long ll;
int a[N] , val[N] , cnt[N] , num[410][N];
ll ans[410][410];
int main()
{
    int n , m , si , i , j , k , x , y;
    ll maxn;
    scanf("%d%d" , &n , &m) , si = (int)sqrt(n);
    for(i = 0 ; i < n ; i ++ ) scanf("%d" , &a[i]) , val[i] = a[i];
    sort(val , val + n);
    for(i = 0 ; i < n ; i ++ ) a[i] = lower_bound(val , val + n , a[i]) - val;
    for(i = 0 ; i <= (n - 1) / si ; i ++ )
    {
        for(j = i * si ; j < (i + 1) * si && j < n ; j ++ ) cnt[a[j]] ++ ;
        for(j = 0 ; j < n ; j ++ ) num[i][j] = cnt[j];
    }
    for(i = 0 ; i <= (n - 1) / si ; i ++ )
    {
        memset(cnt , 0 , sizeof(cnt)) , maxn = 0;
        for(j = i ; j <= (n - 1) / si ; j ++ )
        {
            for(k = j * si ; k < (j + 1) * si && k < n ; k ++ ) cnt[a[k]] ++ , maxn = max(maxn , (ll)cnt[a[k]] * val[a[k]]);
            ans[i][j] = maxn;
        }
    }
    memset(cnt , 0 , sizeof(cnt));
    while(m -- )
    {
        scanf("%d%d" , &x , &y) , x -- , y -- ;
        if(y / si - x / si < 2)
        {
            maxn = 0;
            for(i = x ; i <= y ; i ++ ) cnt[a[i]] ++ , maxn = max(maxn , (ll)cnt[a[i]] * val[a[i]]);
            for(i = x ; i <= y ; i ++ ) cnt[a[i]] -- ;
        }
        else
        {
            maxn = ans[x / si + 1][y / si - 1];
            for(i = x ; i < (x / si + 1) * si ; i ++ ) cnt[a[i]] ++ , maxn = max(maxn , (ll)(cnt[a[i]] + num[y / si - 1][a[i]] - num[x / si][a[i]]) * val[a[i]]);
            for(i = y / si * si ; i <= y ; i ++ ) cnt[a[i]] ++ , maxn = max(maxn , (ll)(cnt[a[i]] + num[y / si - 1][a[i]] - num[x / si][a[i]]) * val[a[i]]);
            for(i = x ; i < (x / si + 1) * si ; i ++ ) cnt[a[i]] -- ;
            for(i = y / si * si ; i <= y ; i ++ ) cnt[a[i]] -- ;
        }
        printf("%lld\n" , maxn);
    }
    return 0;
}

10.KD-tree(bzoj3053)

#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <algorithm>
#define N 50010
#define squ(x) (x) * (x)
#define rep for(int i = 0 ; i < m ; i ++ )
using namespace std;
typedef pair<int , int> pr;
priority_queue<pr> q;
struct data
{
	int p[5] , mx[5] , mn[5] , c[2];
}a[N];
int v[5] , d , root , m , ans , tmp[20];
bool cmp(data a , data b)
{
	rep
	{
		if(a.p[(d + i) % m] < b.p[(d + i) % m]) return 1;
		if(a.p[(d + i) % m] > b.p[(d + i) % m]) return 0;
	}
	return 0;
}
void pushup(int k , int x)
{
	rep a[k].mx[i] = max(a[k].mx[i] , a[x].mx[i]) , a[k].mn[i] = min(a[k].mn[i] , a[x].mn[i]);
}
int build(int l , int r , int now)
{
	int mid = (l + r) >> 1;
	d = now , nth_element(a + l , a + mid , a + r + 1 , cmp);
	rep a[mid].mx[i] = a[mid].mn[i] = a[mid].p[i];
	a[mid].c[0] = a[mid].c[1] = 0;
	if(l < mid) a[mid].c[0] = build(l , mid - 1 , (now + 1) % m) , pushup(mid , a[mid].c[0]);
	if(r > mid) a[mid].c[1] = build(mid + 1 , r , (now + 1) % m) , pushup(mid , a[mid].c[1]);
	return mid;
}
int getdis(int k)
{
	if(!k) return 0x7fffffff;
	int ans = 0;
	rep
	{
		if(v[i] < a[k].mn[i]) ans += squ(v[i] - a[k].mn[i]);
		if(v[i] > a[k].mx[i]) ans += squ(v[i] - a[k].mx[i]);
	}
	return ans;
}
void query(int k)
{
	int dn = 0 , dl = getdis(a[k].c[0]) , dr = getdis(a[k].c[1]);
	rep dn += squ(v[i] - a[k].p[i]);
	if(dn < q.top().first) q.pop() , q.push(pr(dn , k));
	if(dl < dr)
	{
		if(dl < q.top().first) query(a[k].c[0]);
		if(dr < q.top().first) query(a[k].c[1]);
	}
	else
	{
		if(dr < q.top().first) query(a[k].c[1]);
		if(dl < q.top().first) query(a[k].c[0]);
	}
}
int main()
{
	int n , k , i , j , t;
	while(scanf("%d%d" , &n , &m) != EOF)
	{
		for(i = 1 ; i <= n ; i ++ )
			for(j = 0 ; j < m ; j ++ )
				scanf("%d" , &a[i].p[j]);
		root = build(1 , n , 0);
		scanf("%d" , &k);
		while(k -- )
		{
			for(i = 0 ; i < m ; i ++ ) scanf("%d" , &v[i]);
			scanf("%d" , &t);
			for(i = 1 ; i <= t ; i ++ ) q.push(pr(0x7fffffff , 0));
			query(root);
			for(i = 1 ; i <= t ; i ++ ) tmp[i] = q.top().second , q.pop();
			printf("the closest %d points are:\n" , t);
			for(i = t ; i >= 1 ; i -- )
			{
				for(j = 0 ; j < m - 1 ; j ++ ) printf("%d " , a[tmp[i]].p[j]);
				printf("%d\n" , a[tmp[i]].p[m - 1]);
			}
		}
	}
	return 0;
}

11.Link-Cut-Tree(bzoj4025)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
struct data
{
	int x , y , t1 , t2;
}a[N << 1];
int n , fa[N << 2] , c[2][N << 2] , si[N << 2] , w[N << 2] , mp[N << 2] , rev[N << 2] , num[N] , sum , now;
inline char nc()
{
	static char buf[100000] , *p1 , *p2;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ;
}
inline int read()
{
	int ret = 0; char ch = nc();
	while(ch < ‘0‘ || ch > ‘9‘) ch = nc();
	while(ch >= ‘0‘ && ch <= ‘9‘) ret = (ret << 3) + (ret << 1) + ch - 48 , ch = nc();
	return ret;
}
bool cmp(data a , data b)
{
	return a.t1 < b.t1;
}
void pushup(int x)
{
	si[x] = si[c[0][x]] + si[c[1][x]] + 1;
	mp[x] = x;
	if(w[mp[c[0][x]]] < w[mp[x]]) mp[x] = mp[c[0][x]];
	if(w[mp[c[1][x]]] < w[mp[x]]) mp[x] = mp[c[1][x]];
}
void pushdown(int x)
{
	if(rev[x])
	{
		int l = c[0][x] , r = c[1][x];
		swap(c[0][l] , c[1][l]) , swap(c[0][r] , c[1][r]);
		rev[l] ^= 1 , rev[r] ^= 1 , rev[x] = 0;
	}
}
bool isroot(int x)
{
	return c[0][fa[x]] != x && c[1][fa[x]] != x;
}
void update(int x)
{
	if(!isroot(x)) update(fa[x]);
	pushdown(x);
}
void rotate(int x)
{
	int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
	if(!isroot(y)) c[c[1][z] == y][z] = x;
	fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
	pushup(y) , pushup(x);
}
void splay(int x)
{
	update(x);
	while(!isroot(x))
	{
		int y = fa[x] , z = fa[y];
		if(!isroot(y))
		{
			if((c[0][y] == x) ^ (c[0][z] == y)) rotate(x);
			else rotate(y);
		}
		rotate(x);
	}
}
void access(int x)
{
	int t = 0;
	while(x) splay(x) , c[1][x] = t , pushup(x) , t = x , x = fa[x];
}
int find(int x)
{
	access(x) , splay(x);
	while(c[0][x]) pushdown(x) , x = c[0][x];
	return x;
}
void makeroot(int x)
{
	access(x) , splay(x);
	swap(c[0][x] , c[1][x]) , rev[x] ^= 1;
}
void link(int x , int y)
{
	makeroot(x) , fa[x] = y;
}
void cut(int x , int y)
{
	makeroot(x) , access(y) , splay(y) , fa[x] = c[0][y] = 0 , pushup(y);
}
void split(int x , int y)
{
	makeroot(x) , access(y) , splay(y);
}
void add(int p)
{
	int tx = a[p].x , ty = a[p].y , tmp , flag = 0;
	if(tx == ty && a[p].t2 > now) num[a[p].t2] ++ , sum ++ ;
	else
	{
		if(find(tx) != find(ty)) link(p + n , tx) , link(p + n , ty);
		else
		{
			split(tx , ty);
			if(!((si[ty] >> 1) & 1)) flag = 1;
			if(w[mp[ty]] >= a[p].t2) tmp = p;
			else tmp = mp[ty] - n , cut(tmp + n , a[tmp].x) , cut(tmp + n , a[tmp].y) , link(p + n , tx) , link(p + n , ty);
			if(flag && a[tmp].t2 > now) num[a[tmp].t2] ++ , sum ++ ;
		}
	}
}
int main()
{
	int m , t , i , p = 1;
	n = read() , m = read() , t = read();
	for(i = 1 ; i <= m ; i ++ ) a[i].x = read() , a[i].y = read() , a[i].t1 = read() , a[i].t2 = read();
	sort(a + 1 , a + m + 1 , cmp);
	for(i = 1 ; i <= n + m ; i ++ ) si[i] = 1 , mp[i] = i;
	for(i = 0 ; i <= n ; i ++ ) w[i] = 1 << 30;
	for(i = 1 ; i <= m ; i ++ ) w[i + n] = a[i].t2;
	for(i = 0 ; i < t ; i ++ )
	{
		now = i;
		while(p <= m && a[p].t1 <= i) add(p ++ );
		sum -= num[i];
		if(sum) puts("No");
		else puts("Yes");
	}
	return 0;
}

12.可并堆(bzoj2333)

#include <cstdio>
#include <set>
#define N 300010
using namespace std;
multiset<int> s;
multiset<int>::iterator it;
int w[N] , fa[N] , l[N] , r[N] , d[N] , add[N];
char str[5];
void pushdown(int x)
{
    if(add[x]) w[l[x]] += add[x] , w[r[x]] += add[x] , add[l[x]] += add[x] , add[r[x]] += add[x] , add[x] = 0;
}
void update(int x)
{
    if(fa[x]) update(fa[x]);
    pushdown(x);
}
int find(int x)
{
    return fa[x] ? find(fa[x]) : x;
}
int merge(int x , int y)
{
    if(!x) return y;
    if(!y) return x;
    pushdown(x) , pushdown(y);
    if(w[x] < w[y]) swap(x , y);
    r[x] = merge(r[x] , y) , fa[r[x]] = x;
    if(d[l[x]] < d[r[x]]) swap(l[x] , r[x]);
    d[x] = d[r[x]] + 1;
    return x;
}
int clear(int x)
{
    int t = merge(l[x] , r[x]) , f = fa[x];
    fa[x] = l[x] = r[x] = 0;
    if(x == l[f]) l[f] = t;
    else r[f] = t;
    fa[t] = f;
    return find(t);
}
void del(int x)
{
    s.erase(s.find(x));
}
int main()
{
    int n , i , m , v = 0 , x , y , tx , ty;
    scanf("%d" , &n);
    for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &w[i]) , s.insert(w[i]);
    scanf("%d" , &m);
    d[0] = -1;
    while(m -- )
    {
        scanf("%s" , str);
        if(str[0] == ‘U‘)
        {
            scanf("%d%d" , &x , &y) , tx = find(x) , ty = find(y);
            if(tx != ty)
            {
                if(merge(tx , ty) == tx) del(w[ty]);
                else del(w[tx]);
            }
        }
        else if(str[0] == ‘A‘)
        {
            scanf("%d" , &x);
            if(str[1] == ‘1‘) scanf("%d" , &y) , update(x) , del(w[find(x)]) , w[x] += y , s.insert(w[merge(x , clear(x))]);
            else if(str[1] == ‘2‘) scanf("%d" , &y) , tx = find(x) , del(w[tx]) , w[tx] += y , s.insert(w[tx]) , add[tx] += y;
            else v += x;
        }
        else
        {
            if(str[1] == ‘1‘) scanf("%d" , &x) , update(x) , printf("%d\n" , w[x] + v);
            else if(str[1] == ‘2‘) scanf("%d" , &x) , tx = find(x) , printf("%d\n" , w[tx] + v);
            else printf("%d\n" , *(--s.end()) + v);
        }
    }
    return 0;
}

13.树套树(bzoj4785)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
typedef long long ll;
const ll mod = 998244353;
int root[N << 2] , ls[N << 8] , rs[N << 8] , tot , n;
ll sum[N << 8];
ll cal(ll x , ll y)
{
    return (x * y + (1 - x + mod) * (1 - y + mod)) % mod;
}
ll pow(ll x , ll y)
{
    ll ans = 1;
    while(y)
    {
        if(y & 1) ans = ans * x % mod;
        x = x * x % mod , y >>= 1;
    }
    return ans;
}
void update(int b , int e , ll v , int l , int r , int &x)
{
    if(!x) x = ++tot , sum[x] = 1;
    if(b <= l && r <= e)
    {
        sum[x] = cal(sum[x] , v);
        return;
    }
    int mid = (l + r) >> 1;
    if(b <= mid) update(b , e , v , l , mid , ls[x]);
    if(e > mid) update(b , e , v , mid + 1 , r , rs[x]);
}
ll query(int p , int l , int r , int x)
{
    if(!x) return 1;
    if(l == r) return sum[x];
    int mid = (l + r) >> 1;
    if(p <= mid) return cal(sum[x] , query(p , l , mid , ls[x]));
    else return cal(sum[x] , query(p , mid + 1 , r , rs[x]));
}
void modify(int p , int q , ll v , int b , int e , int l , int r , int x)
{
    if(p <= l && r <= q)
    {
        update(b , e , v , 1 , n , root[x]);
        return;
    }
    int mid = (l + r) >> 1;
    if(p <= mid) modify(p , q , v , b , e , l , mid , x << 1);
    if(q > mid) modify(p , q , v , b , e , mid + 1 , r , x << 1 | 1);
}
ll solve(int p , int q , int l , int r , int x)
{
    if(l == r) return query(q , 1 , n , root[x]);
    int mid = (l + r) >> 1;
    if(p <= mid) return cal(query(q , 1 , n , root[x]) , solve(p , q , l , mid , x << 1));
    else return cal(query(q , 1 , n , root[x]) , solve(p , q , mid + 1 , r , x << 1 | 1));
}
int main()
{
    int m , opt , l , r;
    ll p;
    scanf("%d%d" , &n , &m);
    while(m -- )
    {
        scanf("%d%d%d" , &opt , &l , &r);
        if(opt == 1)
        {
            p = pow(r - l + 1 , mod - 2);
            if(l > 1) modify(1 , l - 1 , (1 - p + mod) % mod , l , r , 0 , n , 1) , modify(0 , 0 , 0 , 1 , l - 1 , 0 , n , 1);
            if(r < n) modify(l , r , (1 - p + mod) % mod , r + 1 , n , 0 , n , 1) , modify(0 , 0 , 0 , r + 1 , n , 0 , n , 1);
            modify(l , r , (1 - (p << 1) % mod + mod) % mod , l , r , 0 , n , 1) , modify(0 , 0 , p , l , r , 0 , n , 1);
        }
        else printf("%lld\n" , solve(l - 1 , r , 0 , n , 1));
    }
    return 0;
}

二、数论

1.欧拉函数(bzoj4173)

#include <cstdio>
typedef long long ll;
const ll mod = 998244353;
ll phi(ll n)
{
	ll i , ans = n;
	for(i = 2 ; i * i <= n ; i ++ )
	{
		if(n % i == 0)
		{
			ans = ans / i * (i - 1);
			while(n % i == 0) n /= i;
		}
	}
	if(n != 1) ans = ans / n * (n - 1);
	return ans % mod;
}
int main()
{
	ll n , m;
	scanf("%lld%lld" , &n , &m);
	printf("%lld\n" , phi(n) * phi(m) % mod * (n % mod) % mod * (m % mod) % mod);
	return 0;
}

2.Lucas定理(bzoj2982)

#include <cstdio>
#define mod 10007
int fac[10010];
int pow(int x , int y)
{
    int ans = 1;
    while(y)
    {
        if(y & 1) ans = ans * x % mod;
        x = x * x % mod , y >>= 1;
    }
    return ans;
}
int cal(int n , int m)
{
    if(n < m) return 0;
    return fac[n] * pow(fac[m] , mod - 2) % mod * pow(fac[n - m] , mod - 2) % mod;
}
int lucas(int n , int m)
{
    if(!m) return 1;
    return cal(n % mod , m % mod) * lucas(n / mod , m / mod) % mod;
}
int main()
{
    int t , n , m , i;
    scanf("%d" , &t);
    fac[0] = 1;
    for(i = 1 ; i < mod ; i ++ ) fac[i] = fac[i - 1] * i % mod;
    while(t -- )
    {
        scanf("%d%d" , &n , &m);
        printf("%d\n" , lucas(n , m));
    }
    return 0;
}

3.递推乘法逆元(loj110)

#include <cstdio>
typedef long long ll;
ll ine[3000010];
int main()
{
	ll n , p , i;
	scanf("%lld%lld" , &n , &p);
	ine[1] = 1 , puts("1");
	for(i = 2 ; i <= n ; i ++ )
		ine[i] = (p - p / i) * ine[p % i] % p , printf("%lld\n" , ine[i]);
	return 0;
}

4.高斯消元(bzoj1923)

#include <cstdio>
#include <bitset>
using namespace std;
bitset<1010> a[2010];
int n , m , ans;
char str[1010];
void gauss()
{
	int i , j;
	for(i = 1 ; i <= n ; i ++ )
	{
		for(j = i ; j <= m && !a[j][i] ; j ++ );
		if(j > m)
		{
			ans = 0;
			return;
		}
		else ans = max(ans , j);
		swap(a[i] , a[j]);
		for(j = 1 ; j <= m ; j ++ )
			if(j != i && a[j][i])
				a[j] ^= a[i];
	}
}
int main()
{
	int i , j , t;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= m ; i ++ )
	{
		scanf("%s" , str + 1);
		for(j = 1 ; j <= n ; j ++ ) a[i][j] = str[j] - ‘0‘;
		scanf("%d" , &t) , a[i][n + 1] = t;
	}
	gauss();
	if(!ans)
	{
		printf("Cannot Determine\n");
		return 0;
	}
	printf("%d\n" , ans);
	for(i = 1 ; i <= n ; i ++ ) printf("%s\n" , a[i][n + 1] ? "?y7M#" : "Earth");
	return 0;
}

5.线性基(bzoj4269)

#include <cstdio>
#include <algorithm>
using namespace std;
int a[100010];
int main()
{
    int n , i , j , tot = 0 , ans = 0;
    scanf("%d" , &n);
    for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
    for(i = 1 << 30 ; i ; i >>= 1)
    {
        for(j = ++tot ; j <= n ; j ++ )
        {
            if(a[j] & i)
            {
                swap(a[tot] , a[j]);
                break;
            }
        }
        if(j > n)
        {
            tot -- ;
            continue;
        }
        for(j = 1 ; j <= n ; j ++ )
            if(j != tot && a[j] & i)
                a[j] ^= a[tot];
    }
    for(i = 1 ; i < tot ; i ++ ) ans ^= a[i];
    printf("%d %d\n" , ans ^ a[tot] , ans);
    return 0;
}

6.矩阵乘法(loj100)

#include <cstdio>
#define N 510
typedef long long ll;
const ll mod = 1000000007;
ll a[N][N] , b[N][N] , c[N][N];
int main()
{
	int n , m , p , i , j , k;
	scanf("%d%d%d" , &n , &p , &m);
	for(i = 1 ; i <= n ; i ++ )
		for(j = 1 ; j <= p ; j ++ )
			scanf("%lld" , &a[i][j]);
	for(i = 1 ; i <= p ; i ++ )
		for(j = 1 ; j <= m ; j ++ )
			scanf("%lld" , &b[i][j]);
	for(i = 1 ; i <= n ; i ++ )
		for(j = 1 ; j <= m ; j ++ )
			for(k = 1 ; k <= p ; k ++ )
				c[i][j] = ((c[i][j] + a[i][k] * b[k][j]) % mod + mod) % mod;
	for(i = 1 ; i <= n ; i ++ )
	{
		for(j = 1 ; j <= m ; j ++ )
			printf("%lld " , c[i][j]);
		printf("\n");
	}
	return 0;
}

7.FFT(loj108)

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 400010
using namespace std;
const double pi = acos(-1);
struct data
{
	double x , y;
	data() {}
	data(double x0 , double y0) {x = x0 , y = y0;}
	data operator+(data a) {return data(x + a.x , y + a.y);}
	data operator-(data a) {return data(x - a.x , y - a.y);}
	data operator*(data a) {return data(x * a.x - y * a.y , x * a.y + y * a.x);}
}a[N] , b[N];
void fft(data *a , int len , int flag)
{
	int i , j , k;
	for(i = k = 0 ; i < len ; i ++ )
	{
		if(i > k) swap(a[i] , a[k]);
		for(j = len >> 1 ; (k ^= j) < j ; j >>= 1);
	}
	for(k = 2 ; k <= len ; k <<= 1)
	{
		data wn(cos(2 * pi * flag / k) , sin(2 * pi * flag / k));
		for(i = 0 ; i < len ; i += k)
		{
			data w(1 , 0) , t;
			for(j = i ; j < i + (k >> 1) ; j ++ , w = w * wn)
				t = w * a[j + (k >> 1)] , a[j + (k >> 1)] = a[j] - t , a[j] = a[j] + t;
		}
	}
}
void work(data *a , data *b , int len)
{
	int i;
	fft(a , len , 1) , fft(b , len , 1);
	for(i = 0 ; i < len ; i ++ ) a[i] = a[i] * b[i];
	fft(a , len , -1);
	for(i = 0 ; i < len ; i ++ ) a[i].x /= len;
}
int main()
{
	int n , m , i , len = 1;
	scanf("%d%d" , &n , &m);
	for(i = 0 ; i <= n ; i ++ ) scanf("%lf" , &a[i].x);
	for(i = 0 ; i <= m ; i ++ ) scanf("%lf" , &b[i].x);
	while(len <= n + m) len <<= 1;
	work(a , b , len);
	for(i = 0 ; i < n + m ; i ++ ) printf("%d " , (int)(a[i].x + 0.1));
	printf("%d" , (int)(a[n + m].x + 0.1));
	return 0;
}

三、图论

1.堆优化Dijkstra(loj119)

#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#define N 2510
#define M 12510
using namespace std;
typedef long long ll;
typedef pair<ll , int> pr;
priority_queue<pr> q;
int head[N] , to[M] , next[M] , cnt;
ll len[M] , dis[N];
bool vis[N];
void add(int x , int y , ll z)
{
	to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
int main()
{
	int n , m , s , t , i , x , y;
	ll z;
	scanf("%d%d%d%d" , &n , &m , &s , &t);
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%lld" , &x , &y , &z) , add(x , y , z) , add(y , x , z);
	memset(dis , 0x3f , sizeof(dis));
	dis[s] = 0 , q.push(pr(0 , s));
	while(!q.empty())
	{
		x = q.top().second , q.pop();
		if(vis[x]) continue;
		vis[x] = 1;
		for(i = head[x] ; i ; i = next[i])
			if(dis[to[i]] > dis[x] + len[i])
				dis[to[i]] = dis[x] + len[i] , q.push(pr(-dis[to[i]] , to[i]));
	}
	printf("%lld\n" , dis[t]);
	return 0;
}

2.倍增Floyd(bzoj4773)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 310
using namespace std;
int n , log[N];
struct data
{
    int v[N][N];
    data()
    {
        memset(v , 0x3f , sizeof(v));
    }
    data operator*(const data a)const
    {
        data ans;
        int i , j , k;
        for(k = 1 ; k <= n ; k ++ )
            for(i = 1 ; i <= n ; i ++ )
                for(j = 1 ; j <= n ; j ++ )
                    ans.v[i][j] = min(ans.v[i][j] , v[i][k] + a.v[k][j]);
        return ans;
    }
}dis[10] , tmp;
bool judge(data a)
{
    int i;
    for(i = 1 ; i <= n ; i ++ )
        if(a.v[i][i] < 0)
            return 1;
    return 0;
}
int main()
{
    int m , x , y , z , i , sum = 0;
    scanf("%d%d" , &n , &m);
    for(i = 1 ; i <= n ; i ++ ) dis[0].v[i][i] = tmp.v[i][i] = 0;
    for(i = 2 ; i <= n ; i ++ ) log[i] = log[i >> 1] + 1;
    while(m -- ) scanf("%d%d%d" , &x , &y , &z) , dis[0].v[x][y] = z;
    for(i = 1 ; i <= log[n] ; i ++ ) dis[i] = dis[i - 1] * dis[i - 1];
    for(i = log[n] ; ~i ; i -- )
        if(!judge(tmp * dis[i]))
            tmp = tmp * dis[i] , sum += (1 << i);
    tmp = tmp * dis[0];
    printf("%d\n" , judge(tmp) ? sum + 1 : 0);
    return 0;
}

3.分层图Spfa(bzoj2662)

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
queue<pair<int , int> > q;
int head[60] , to[2010] , len[2010] , next[2010] , cnt , dis[60][60] , inq[60][60];
void add(int x , int y , int z)
{
    to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
int main()
{
    int n , m , k , i , x , y , z , ans = 0x3f3f3f3f;
    scanf("%d%d%d" , &n , &m , &k);
    while(m -- ) scanf("%d%d%d" , &x , &y , &z) , add(x , y , z) , add(y , x , z);
    memset(dis , 0x3f , sizeof(dis));
    dis[1][0] = 0 , q.push(make_pair(1 , 0));
    while(!q.empty())
    {
        x = q.front().first , y = q.front().second , q.pop() , inq[x][y] = 0;
        for(i = head[x] ; i ; i = next[i])
        {
            if(dis[to[i]][y] > dis[x][y] + len[i])
            {
                dis[to[i]][y] = dis[x][y] + len[i];
                if(!inq[to[i]][y]) inq[to[i]][y] = 1 , q.push(make_pair(to[i] , y));
            }
            if(y < k && dis[to[i]][y + 1] > dis[x][y] + len[i] / 2)
            {
                dis[to[i]][y + 1] = dis[x][y] + len[i] / 2;
                if(!inq[to[i]][y + 1]) inq[to[i]][y + 1] = 1 , q.push(make_pair(to[i] , y + 1));
            }
        }
    }
    for(i = 0 ; i <= k ; i ++ ) ans = min(ans , dis[n][i]);
    printf("%d\n" , ans);
    return 0;
}

4.Kruscal(bzoj1821)

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct data
{
    int x , y , z;
}a[1000010];
int dx[1010] , dy[1010] , cnt , f[1010];
bool cmp(data a , data b)
{
    return a.z < b.z;
}
int find(int x)
{
    return x == f[x] ? x : f[x] = find(f[x]);
}
int main()
{
    int n , k , i , j , cedge = 0 , tx , ty;
    scanf("%d%d" , &n , &k);
    for(i = 1 ; i <= n ; i ++ )
        scanf("%d%d" , &dx[i] , &dy[i]);
    for(i = 1 ; i <= n ; i ++ )
        for(j = i + 1 ; j <= n ; j ++ )
            a[++cnt].x = i , a[cnt].y = j , a[cnt].z = (dx[i] - dx[j]) * (dx[i] - dx[j]) + (dy[i] - dy[j]) * (dy[i] - dy[j]);
    sort(a + 1 , a + cnt + 1 , cmp);
    for(i = 1 ; i <= n ; i ++ )
        f[i] = i;
    for(i = 1 ; i <= cnt ; i ++ )
    {
        tx = find(a[i].x) , ty = find(a[i].y);
        if(tx != ty)
        {
            if(cedge == n - k)
            {
                printf("%.2lf\n" , sqrt(a[i].z));
                return 0;
            }
            else f[tx] = ty , cedge ++ ;
        }
    }
    return 0;
}

5.倍增LCA(bzoj1787)

#include <cstdio>
#include <algorithm>
using namespace std;
int head[500010] , to[1000010] , next[1000010] , cnt , log[500010] , fa[500010][21] , deep[500010];
void add(int x , int y)
{
    to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x)
{
    int i;
    for(i = 1 ; i <= log[deep[x]] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for(i = head[x] ; i ; i = next[i])
        if(to[i] != fa[x][0])
            fa[to[i]][0] = x , deep[to[i]] = deep[x] + 1 , dfs(to[i]);
}
int getlca(int x , int y)
{
    int i;
    if(deep[x] < deep[y]) swap(x , y);
    for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
        if(deep[x] - (1 << i) >= deep[y])
            x = fa[x][i];
    if(x == y) return x;
    for(i = log[deep[x]] ; ~i ; i -- )
        if(fa[x][i] != fa[y][i])
            x = fa[x][i] , y = fa[y][i];
    return fa[x][0];
}
int main()
{
    int n , m , i , x , y , z , xy , xz , yz , t;
    scanf("%d%d" , &n , &m);
    for(i = 1 ; i < n ; i ++ )
        scanf("%d%d" , &x , &y) , add(x , y) , add(y , x);
    for(i = 2 ; i <= n ; i ++ ) log[i] = log[i >> 1] + 1;
    dfs(1);
    while(m -- )
    {
        scanf("%d%d%d" , &x , &y , &z);
        xy = getlca(x , y) , xz = getlca(x , z) , yz = getlca(y , z) , t = deep[x] + deep[y] + deep[z] - 2 * deep[getlca(xy , z)];
        if(deep[xy] > deep[xz] && deep[xy] > deep[yz]) printf("%d %d\n" , xy , t - deep[xy]);
        else if(deep[xz] > deep[yz]) printf("%d %d\n" , xz , t - deep[xz]);
        else printf("%d %d\n" , yz , t - deep[yz]);
    }
    return 0;
}

6.树链剖分(bzoj4196)

#include <cstdio>
#include <cstring>
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
#define N 100100
int fa[N] , bl[N] , deep[N] , si[N] , pos[N] , tot;
int head[N] , to[N] , next[N] , cnt;
int sum[N << 2] , tag[N << 2] , n;
char str[20];
inline int read()
{
    int num = 0;
    char ch;
    while(ch < ‘0‘ || ch > ‘9‘) ch = getchar();
    while(ch >= ‘0‘ && ch <= ‘9‘) num = num * 10 + ch - ‘0‘ , ch = getchar();
    return num;
}
void add(int x , int y)
{
    to[++cnt] = y;
    next[cnt] = head[x];
    head[x] = cnt;
}
void dfs1(int x)
{
    int i;
    si[x] = 1;
    for(i = head[x] ; i ; i = next[i])
    {
        deep[to[i]] = deep[x] + 1;
        dfs1(to[i]);
        si[x] += si[to[i]];
    }
}
void dfs2(int x , int c)
{
    int i , k = n + 1;
    pos[x] = ++tot;
    bl[x] = c;
    for(i = head[x] ; i ; i = next[i])
        if(si[to[i]] > si[k])
            k = to[i];
    if(k != n + 1)
    {
        dfs2(k , c);
        for(i = head[x] ; i ; i = next[i])
            if(to[i] != k)
                dfs2(to[i] , to[i]);
    }
}
void pushup(int x)
{
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
}
void pushdown(int x , int m)
{
    if(tag[x] != -1)
    {
        sum[x << 1] = tag[x] * (m - (m >> 1));
        sum[x << 1 | 1] = tag[x] * (m >> 1);
        tag[x << 1] = tag[x << 1 | 1] = tag[x];
        tag[x] = -1;
    }
}
void update(int b , int e , int a , int l , int r , int x)
{
    if(b <= l && r <= e)
    {
        sum[x] = a * (r - l + 1);
        tag[x] = a;
        return;
    }
    pushdown(x , r - l + 1);
    int mid = (l + r) >> 1;
    if(b <= mid) update(b , e , a , lson);
    if(e > mid) update(b , e , a , rson);
    pushup(x);
}
int query(int b , int e , int l , int r , int x)
{
    if(b <= l && r <= e)
        return sum[x];
    pushdown(x , r - l + 1);
    int mid = (l + r) >> 1 , ans = 0;
    if(b <= mid) ans += query(b , e , lson);
    if(e > mid) ans += query(b , e , rson);
    return ans;
}
void solveupdate(int x)
{
    while(bl[x])
    {
        update(pos[bl[x]] , pos[x] , 1 , 1 , n , 1);
        x = fa[bl[x]];
    }
    update(1 , pos[x] , 1 , 1 , n , 1);
}
int solvequery(int x)
{
    int ans = 0;
    while(bl[x])
    {
        ans += query(pos[bl[x]] , pos[x] , 1 , n , 1);
        x = fa[bl[x]];
    }
    ans += query(1 , pos[x] , 1 , n , 1);
    return ans;
}
int main()
{
    int i , q , x;
    n = read();
    for(i = 1 ; i < n ; i ++ )
    {
        fa[i] = read();
        add(fa[i] , i);
    }
    dfs1(0);
    dfs2(0 , 0);
    memset(tag , -1 , sizeof(tag));
    q = read();
    while(q -- )
    {
        scanf("%s" , str);
        x = read();
        if(str[0] == ‘i‘)
        {
            printf("%d\n" , deep[x] - solvequery(x) + 1);
            solveupdate(x);
        }
        else
        {
            printf("%d\n" , query(pos[x] , pos[x] + si[x] - 1 , 1 , n , 1));
            update(pos[x] , pos[x] + si[x] - 1 , 0 , 1 , n , 1);
        }
    }
    return 0;
}

7.Tarjan(bzoj1529)

#include <cstdio>
#include <algorithm>
using namespace std;
int a[1000010] , deep[1000010] , low[1000010] , tot , sta[1000010] , top , vis[1000010] , ins[1000010] , bel[1000010] , cnt , cd[1000010];
void tarjan(int x)
{
    deep[x] = low[x] = ++tot;
    ins[x] = vis[x] = 1;
    sta[++top] = x;
    if(!vis[a[x]])
        tarjan(a[x]) , low[x] = min(low[x] , low[a[x]]);
    else if(ins[a[x]])
        low[x] = min(low[x] , deep[a[x]]);
    if(deep[x] == low[x])
    {
        int t;
        cnt ++ ;
        do
        {
            t = sta[top -- ];
            ins[t] = 0;
            bel[t] = cnt;
        }while(t != x);
    }
}
int main()
{
    int n , i , ans = 0;
    scanf("%d" , &n);
    for(i = 1 ; i <= n ; i ++ )
        scanf("%d" , &a[i]);
    for(i = 1 ; i <= n ; i ++ )
        if(!vis[i])
            tarjan(i);
    for(i = 1 ; i <= n ; i ++ )
        if(bel[i] != bel[a[i]])
            cd[bel[i]] ++ ;
    for(i = 1 ; i <= cnt ; i ++ )
        if(!cd[i])
            ans ++ ;
    printf("%d\n" , ans);
    return 0;
}

8.拓扑排序(bzoj4562)

#include <cstdio>
#include <cstring>
#include <queue>
#define N 100010
using namespace std;
queue<int> q;
int head[N] , to[N << 1] , next[N << 1] , cnt , rd[N] , cd[N] , f[N];
void add(int x , int y)
{
    to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
int main()
{
    int n , m , i , x , y , ans = 0;
    scanf("%d%d" , &n , &m);
    for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , cd[x] ++ , rd[y] ++ ;
    for(i = 1 ; i <= n ; i ++ )
    {
        if(!rd[i])
        {
            if(cd[i]) f[i] = 1;
            q.push(i);
        }
    }
    while(!q.empty())
    {
        x = q.front() , q.pop();
        for(i = head[x] ; i ; i = next[i])
        {
            f[to[i]] += f[x] , rd[to[i]] -- ;
            if(!rd[to[i]]) q.push(to[i]);
        }
    }
    for(i = 1 ; i <= n ; i ++ ) if(!cd[i]) ans += f[i];
    printf("%d\n" , ans);
    return 0;
}

四、字符串

1.KMP(luogu3375)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s1[1000010] , s2[1010];
int nxt[1010];
int main()
{
	int n , m , i , j;
	scanf("%s%s" , s1 , s2) , n = strlen(s1) , m = strlen(s2);
	nxt[0] = -1;
	for(i = 1 , j = -1 ; i <= m ; i ++ )
	{
		while(~j && s2[j] != s2[i - 1]) j = nxt[j];
		nxt[i] = ++j;
	}
	for(i = j = 0 ; i < n ; i ++ )
	{
		while(~j && s1[i] != s2[j]) j = nxt[j];
		j ++ ;
		if(j == m) printf("%d\n" , i - m + 2) , j = nxt[j];
	}
	for(i = 1 ; i <= m ; i ++ ) printf("%d " , nxt[i]);
	return 0;
}

2.Hash(bzoj2081)

#include <cstdio>
#include <map>
#define N 200010
using namespace std;
typedef unsigned long long ull;
struct data
{
    ull b[N] , h1[N] , h2[N];
    ull hash(int l , int r)
    {
        return (h1[r] - h1[l - 1] * b[r - l + 1]) * (h2[l] - h2[r + 1] * b[r - l + 1]);
    }
}t1 , t2;
map<pair<ull , ull> , bool> f;
int a[N] , sta[N] , top;
int main()
{
    int n , i , j , cnt , ans = 0;
    scanf("%d" , &n);
    t1.b[0] = t2.b[0] = 1;
    for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
    for(i = 1 ; i <= n ; i ++ ) t1.b[i] = t1.b[i - 1] * 233 , t2.b[i] = t2.b[i - 1] * 2333;
    for(i = 1 ; i <= n ; i ++ ) t1.h1[i] = t1.h1[i - 1] * 233 + a[i] , t2.h1[i] = t2.h1[i - 1] * 2333 + a[i];
    for(i = n ; i >= 1 ; i -- ) t1.h2[i] = t1.h2[i + 1] * 233 + a[i] , t2.h2[i] = t2.h2[i + 1] * 2333 + a[i];
    for(i = 1 ; i <= n ; i ++ )
    {
        f.clear() , cnt = 0;
        for(j = 1 ; j + i - 1 <= n ; j += i)
            if(!f[make_pair(t1.hash(j , j + i - 1) , t2.hash(j , j + i - 1))])
                f[make_pair(t1.hash(j , j + i - 1) , t2.hash(j , j + i - 1))] = 1 , cnt ++ ;
        if(cnt > ans) top = 1 , sta[top] = i , ans = cnt;
        else if(cnt == ans) sta[++top] = i;
    }
    printf("%d %d\n" , ans , top);
    for(i = 1 ; i < top ; i ++ ) printf("%d " , sta[i]);
    printf("%d" , sta[top]);
    return 0;
}

3.AC自动机(bzoj4327)

#include <cstdio>
#include <cstring>
#include <queue>
#define N 10000010
using namespace std;
queue<int> q;
int next[N][4] , fail[N] , len[N] , tot = 1 , pos[100010][110];
bool vis[N];
char str[N] , w[N];
int tra(char ch)
{
    return ch == ‘E‘ ? 0 : ch == ‘S‘ ? 1 : ch == ‘W‘ ? 2 : 3;
}
void build()
{
    int x , i;
    for(i = 0 ; i < 4 ; i ++ ) next[0][i] = 1;
    q.push(1);
    while(!q.empty())
    {
        x = q.front() , q.pop();
        for(i = 0 ; i < 4 ; i ++ )
        {
            if(next[x][i]) fail[next[x][i]] = next[fail[x]][i] , q.push(next[x][i]);
            else next[x][i] = next[fail[x]][i];
        }
    }
}
int main()
{
    int n , m , i , j , t;
    scanf("%d%d%s" , &n , &m , str + 1);
    for(i = 1 ; i <= m ; i ++ )
    {
        scanf("%s" , w + 1) , len[i] = strlen(w + 1);
        for(j = t = 1 ; j <= len[i] ; j ++ )
        {
            if(!next[t][tra(w[j])]) next[t][tra(w[j])] = ++tot;
            t = next[t][tra(w[j])] , pos[i][j] = t;
        }
    }
    build();
    vis[1] = 1 , t = 1;
    for(i = 1 ; i <= n ; i ++ )
    {
        t = next[t][tra(str[i])];
        for(j = t ; !vis[j] ; j = fail[j]) vis[j] = 1;
    }
    for(i = 1 ; i <= m ; i ++ )
    {
        for(j = len[i] ; j ; j -- ) if(vis[pos[i][j]]) break;
        printf("%d\n" , j);
    }
    return 0;
}

4.后缀数组(loj111)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using namespace std;
char str[N];
int r[N] , sa[N] , ws[N] , wa[N] , wb[N] , n , m = 129;
void getsa()
{
	int i , j , p , *x = wa , *y = wb;
	for(i = 0 ; i < n ; i ++ ) ws[x[i] = r[i]] ++ ;
	for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
	for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[x[i]]] = i;
	for(p = j = 1 ; p < n ; j <<= 1 , m = p)
	{
		for(p = 0 , i = n - j ; i < n ; i ++ ) y[p ++ ] = i;
		for(i = 0 ; i < n ; i ++ ) if(sa[i] - j >= 0) y[p ++ ] = sa[i] - j;
		for(i = 0 ; i < m ; i ++ ) ws[i] = 0;
		for(i = 0 ; i < n ; i ++ ) ws[x[y[i]]] ++ ;
		for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
		for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[x[y[i]]]] = y[i];
		for(swap(x , y) , x[sa[0]] = 0 , p = i = 1 ; i < n ; i ++ )
		{
			if(y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j]) x[sa[i]] = p - 1;
			else x[sa[i]] = p ++ ;
		}
	}
}
int main()
{
	int i;
	scanf("%s" , str) , n = strlen(str);
	for(i = 0 ; i < n ; i ++ ) r[i] = str[i];
	n ++ , getsa();
	for(i = 1 ; i < n ; i ++ ) printf("%d " , sa[i] + 1);
	return 0;
}

5.后缀自动机(jdoj2939)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200010
using namespace std;
char str[N];
int next[N][26] , fa[N] , dis[N] , tot = 1 , last;
long long ans;
void ins(int c)
{
	int p = last , np = last = ++tot;
	dis[np] = dis[p] + 1;
	while(p && !next[p][c]) next[p][c] = np , p = fa[p];
	if(!p) fa[np] = 1;
	else
	{
		int q = next[p][c];
		if(dis[q] == dis[p] + 1) fa[np] = q;
		else
		{
			int nq = ++tot;
			memcpy(next[nq] , next[q] , sizeof(next[q])) , dis[nq] = dis[p] + 1 , fa[nq] = fa[q] , fa[np] = fa[q] = nq;
			while(p && next[p][c] == q) next[p][c] = nq , p = fa[p];
		}
	}
	ans += dis[np] - dis[fa[np]];
}
int main()
{
	int n , i;
	scanf("%d" , &n);
	while(n -- )
	{
		scanf("%s" , str) , last = 1;
		for(i = 0 ; str[i] ; i ++ ) ins(str[i] - ‘a‘) , printf("%lld\n" , ans);
	}
	return 0;
}

6.Manacher(bzoj2941)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char str[5000010] , tmp[10000010];
int p[10000010];
int main()
{
	int n , i , mx = 0 , last , pos , ans = -1;
	scanf("%s" , str + 1) , n = strlen(str + 1);
	tmp[0] = ‘$‘;
	for(i = 1 ; i <= n ; i ++ ) tmp[(i << 1) - 1] = ‘#‘ , tmp[i << 1] = str[i];
	tmp[n << 1 | 1] = ‘#‘;
	for(i = 1 ; i <= 2 * n ; i ++ )
	{
		if(i <= mx) p[i] = min(p[2 * last - i] , mx - i + 1);
		else p[i] = 1;
		while(tmp[i - p[i]] == tmp[i + p[i]]) p[i] ++ ;
		if(p[i] + i - 1 > mx) mx = p[i] + i - 1 , last = i;
	}
	for(i = 1 ; i <= 2 * n ; i ++ )
		if(p[i] - 1 > ans)
			ans = p[i] - 1 , pos = (i - p[i] + 2) >> 1;
	printf("%d\n%d\n" , pos , ans);
	return 0;
}

五、网络流

1.最大流(loj101)

#include <cstdio>
#include <cstring>
#include <queue>
#define N 1000010
#define M 8000010
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , next[M] , cnt = 1 , s , t , dis[N];
void add(int x , int y , int z)
{
	to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
	to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
}
bool bfs()
{
	int x , i;
	memset(dis , 0 , sizeof(dis));
	while(!q.empty()) q.pop();
	dis[s] = 1 , q.push(s);
	while(!q.empty())
	{
		x = q.front() , q.pop();
		for(i = head[x] ; i ; i = next[i])
		{
			if(val[i] && !dis[to[i]])
			{
				dis[to[i]] = dis[x] + 1;
				if(to[i] == t) return 1;
				q.push(to[i]);
			}
		}
	}
	return 0;
}
int dinic(int x , int low)
{
	if(x == t) return low;
	int temp = low , i , k;
	for(i = head[x] ; i ; i = next[i])
	{
		if(val[i] && dis[to[i]] == dis[x] + 1)
		{
			k = dinic(to[i] , min(temp , val[i]));
			if(!k) dis[to[i]] = 0;
			val[i] -= k , val[i ^ 1] += k;
			if(!(temp -= k)) break;
		}
	}
	return low - temp;
}
int main()
{
	int n , m , i , x , y , z , ans = 0;
	scanf("%d%d%d%d" , &n , &m , &s , &t);
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , add(x , y , z);
	while(bfs()) ans += dinic(s , 0x7fffffff);
	printf("%d\n" , ans);
	return 0;
}

2.最小费用最大流(loj102)

#include <cstdio>
#include <cstring>
#include <queue>
#define N 410
#define M 30010
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , cost[M] , next[M] , cnt = 1 , s , t , dis[N] , inq[N] , from[N] , pre[N];
void add(int x , int y , int v , int c)
{
	to[++cnt] = y , val[cnt] = v , cost[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
	to[++cnt] = x , val[cnt] = 0 , cost[cnt] = -c , next[cnt] = head[y] , head[y] = cnt;
}
bool spfa()
{
	int x , i;
	memset(from , -1 , sizeof(from));
	memset(dis , 0x3f , sizeof(dis));
	dis[s] = 0 , q.push(s);
	while(!q.empty())
	{
		x = q.front() , q.pop() , inq[x] = 0;
		for(i = head[x] ; i ; i = next[i])
		{
			if(val[i] && dis[to[i]] > dis[x] + cost[i])
			{
				dis[to[i]] = dis[x] + cost[i] , from[to[i]] = x , pre[to[i]] = i;
				if(!inq[to[i]]) inq[to[i]] = 1 , q.push(to[i]);
			}
		}
	}
	return ~from[t];
}
int main()
{
	int n , m , i , x , y , v , c , ff = 0 , cc = 0;
	scanf("%d%d" , &n , &m) , s = 1 , t = n;
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d%d" , &x , &y , &v , &c) , add(x , y , v , c);
	while(spfa())
	{
		x = 0x7fffffff;
		for(i = t ; i != s ; i = from[i]) x = min(x , val[pre[i]]);
		ff += x , cc += x * dis[t];
		for(i = t ; i != s ; i = from[i]) val[pre[i]] -= x , val[pre[i] ^ 1] += x;
	}
	printf("%d %d\n" , ff , cc);
	return 0;
}

3.无源汇有上下界可行流(loj115)

#include <cstdio>
#include <cstring>
#include <queue>
#define N 210
#define M 21000
using namespace std;
queue<int> q;
int head[N] , to[M] , low[M] , val[M] , id[M] , next[M] , cnt = 1 , ind[N] , s , t , dis[N] , ans[M];
void add(int x , int y , int l , int r , int i)
{
	to[++cnt] = y , val[cnt] = r - l , next[cnt] = head[x] , head[x] = cnt , low[cnt] = l , id[cnt] = i;
	to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
	ind[x] -= l , ind[y] += l;
}
bool bfs()
{
	int x , i;
	memset(dis , 0 , sizeof(dis));
	while(!q.empty()) q.pop();
	dis[s] = 1 , q.push(s);
	while(!q.empty())
	{
		x = q.front() , q.pop();
		for(i = head[x] ; i ; i = next[i])
		{
			if(val[i] && !dis[to[i]])
			{
				dis[to[i]] = dis[x] + 1;
				if(to[i] == t) return 1;
				q.push(to[i]);
			}
		}
	}
	return 0;
}
int dinic(int x , int low)
{
	if(x == t) return low;
	int temp = low , i , k;
	for(i = head[x] ; i ; i = next[i])
	{
		if(val[i] && dis[to[i]] == dis[x] + 1)
		{
			k = dinic(to[i] , min(temp , val[i]));
			if(!k) dis[to[i]] = 0;
			val[i] -= k , val[i ^ 1] += k;
			if(!(temp -= k)) break;
		}
	}
	return low - temp;
}
int main()
{
	int n , m , i , x , y , l , r , sum = 0;
	scanf("%d%d" , &n , &m) , s = 0 , t = n + 1;
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d%d" , &x , &y , &l , &r) , add(x , y , l , r , i);
	for(i = 1 ; i <= n ; i ++ )
	{
		if(ind[i] > 0) add(s , i , 0 , ind[i] , 0) , sum += ind[i];
		if(ind[i] < 0) add(i , t , 0 , -ind[i] , 0);
	}
	while(bfs()) sum -= dinic(s , 1 << 30);
	if(sum) puts("NO");
	else
	{
		puts("YES");
		for(x = 1 ; x <= n ; x ++ )
			for(i = head[x] ; i ; i = next[i])
				if(id[i])
					ans[id[i]] = low[i] + val[i ^ 1];
		for(i = 1 ; i <= m ; i ++ ) printf("%d\n" , ans[i]);
	}
	return 0;
}

4.有源汇有上下界最大流(loj116)

#include <cstdio>
#include <cstring>
#include <queue>
#define N 210
#define M 21000
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , next[M] , cnt = 1 , s , t , dis[N] , ind[N];
void add(int x , int y , int z)
{
	to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
	to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
}
bool bfs()
{
	int x , i;
	memset(dis , 0 , sizeof(dis));
	while(!q.empty()) q.pop();
	dis[s] = 1 , q.push(s);
	while(!q.empty())
	{
		x = q.front() , q.pop();
		for(i = head[x] ; i ; i = next[i])
		{
			if(val[i] && !dis[to[i]])
			{
				dis[to[i]] = dis[x] + 1;
				if(to[i] == t) return 1;
				q.push(to[i]);
			}
		}
	}
	return 0;
}
int dinic(int x , int low)
{
	if(x == t) return low;
	int temp = low , i , k;
	for(i = head[x] ; i ; i = next[i])
	{
		if(val[i] && dis[to[i]] == dis[x] + 1)
		{
			k = dinic(to[i] , min(temp , val[i]));
			if(!k) dis[to[i]] = 0;
			val[i] -= k , val[i ^ 1] += k;
			if(!(temp -= k)) break;
		}
	}
	return low - temp;
}
int main()
{
	int n , m , b , e , i , x , y , l , r , ans = 0 , sum = 0;
	scanf("%d%d%d%d" , &n , &m , &b , &e) , s = 0 , t = n + 1;
	add(e , b , 1 << 30);
	for(i = 1 ; i <= m ; i ++ )
		scanf("%d%d%d%d" , &x , &y , &l , &r) , add(x , y , r - l) , ind[x] -= l , ind[y] += l;
	for(i = 1 ; i <= n ; i ++ )
	{
		if(ind[i] > 0) add(s , i , ind[i]) , sum += ind[i];
		if(ind[i] < 0) add(i , t , -ind[i]);
	}
	while(bfs()) sum -= dinic(s , 1 << 30);
	if(sum) puts("please go home to sleep");
	else
	{
		ans = val[3] , val[2] = val[3] = 0;
		for(i = head[s] ; i ; i = next[i]) val[i] = val[i ^ 1] = 0;
		for(i = head[t] ; i ; i = next[i]) val[i] = val[i ^ 1] = 0;
		s = b , t = e;
		while(bfs()) ans += dinic(s , 1 << 30);
		printf("%d\n" , ans);
	}
	return 0;
}

5.有源汇有上下界最小流

#include <cstdio>
#include <cstring>
#include <queue>
#define N 210
#define M 21000
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , next[M] , cnt = 1 , s , t , dis[N] , ind[N];
void add(int x , int y , int z)
{
	to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
	to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
}
bool bfs()
{
	int x , i;
	memset(dis , 0 , sizeof(dis));
	while(!q.empty()) q.pop();
	dis[s] = 1 , q.push(s);
	while(!q.empty())
	{
		x = q.front() , q.pop();
		for(i = head[x] ; i ; i = next[i])
		{
			if(val[i] && !dis[to[i]])
			{
				dis[to[i]] = dis[x] + 1;
				if(to[i] == t) return 1;
				q.push(to[i]);
			}
		}
	}
	return 0;
}
int dinic(int x , int low)
{
	if(x == t) return low;
	int temp = low , i , k;
	for(i = head[x] ; i ; i = next[i])
	{
		if(val[i] && dis[to[i]] == dis[x] + 1)
		{
			k = dinic(to[i] , min(temp , val[i]));
			if(!k) dis[to[i]] = 0;
			val[i] -= k , val[i ^ 1] += k;
			if(!(temp -= k)) break;
		}
	}
	return low - temp;
}
int main()
{
	int n , m , b , e , i , x , y , l , r , ans = 0 , sum = 0;
	scanf("%d%d%d%d" , &n , &m , &b , &e) , s = 0 , t = n + 1;
	add(e , b , 1 << 30);
	for(i = 1 ; i <= m ; i ++ )
		scanf("%d%d%d%d" , &x , &y , &l , &r) , add(x , y , r - l) , ind[x] -= l , ind[y] += l;
	for(i = 1 ; i <= n ; i ++ )
	{
		if(ind[i] > 0) add(s , i , ind[i]) , sum += ind[i];
		if(ind[i] < 0) add(i , t , -ind[i]);
	}
	while(bfs()) sum -= dinic(s , 1 << 30);
	if(sum) puts("please go home to sleep");
	else
	{
		ans = val[3] , val[2] = val[3] = 0;
		for(i = head[s] ; i ; i = next[i]) val[i] = val[i ^ 1] = 0;
		for(i = head[t] ; i ; i = next[i]) val[i] = val[i ^ 1] = 0;
		s = b , t = e;
		while(bfs()) ans += dinic(s , 1 << 30);
		printf("%d\n" , ans);
	}
	return 0;
}

六、其它

1.CDQ分治(loj112)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
struct data
{
	int x , y , z , cnt , sum;
}a[N] , tmp[N];
int f[N << 1] , k , tot , ans[N];
bool cmp(data a , data b)
{
	return a.x == b.x ? a.y == b.y ? a.z < b.z : a.y < b.y : a.x < b.x;
}
void add(int x , int a)
{
	int i;
	for(i = x ; i <= k ; i += i & -i ) f[i] += a;
}
int query(int x)
{
	int i , ans = 0;
	for(i = x ; i ; i -= i & -i) ans += f[i];
	return ans;
}
void solve(int l , int r)
{
	if(l >= r) return;
	int mid = (l + r) >> 1 , p1 = l , p2 = mid + 1 , i;
	solve(l , mid) , solve(mid + 1 , r);
	for(i = l ; i <= r ; i ++ )
	{
		if(p1 == mid + 1 || (p2 != r + 1 && a[p2].y < a[p1].y)) a[p2].sum += query(a[p2].z) , tmp[i] = a[p2 ++ ];
		else add(a[p1].z , a[p1].cnt) , tmp[i] = a[p1 ++ ];
	}
	for(i = l ; i <= mid ; i ++ ) add(a[i].z , -a[i].cnt);
	for(i = l ; i <= r ; i ++ ) a[i] = tmp[i];
}
int main()
{
	int n , i;
	scanf("%d%d" , &n , &k);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d%d" , &a[i].x , &a[i].y , &a[i].z);
	sort(a + 1 , a + n + 1 , cmp);
	for(i = 1 ; i <= n ; i ++ )
	{
		if((a[i].x != a[i - 1].x) || (a[i].y != a[i - 1].y) || (a[i].z != a[i - 1].z)) a[++tot] = a[i];
		a[tot].cnt ++ ;
	}
	solve(1 , tot);
	for(i = 1 ; i <= tot ; i ++ ) ans[a[i].sum + a[i].cnt] += a[i].cnt;
	for(i = 1 ; i <= n ; i ++ ) printf("%d\n" , ans[i]);
	return 0;
}

2.单纯形(jdoj2941)

#include <cstdio>
#include <cmath>
#include <algorithm>
#define N 110
using namespace std;
const double eps = 1e-7;
int n , m;
double a[N][N] , b[N] , c[N] , ans;
void pivot(int l , int e)
{
	int i , j;
	b[l] /= a[l][e];
	for(i = 1 ; i <= n ; i ++ ) if(i != e) a[l][i] /= a[l][e];
	a[l][e] = 1 / a[l][e];
	for(i = 1 ; i <= m ; i ++ )
	{
		if(i != l && fabs(a[i][e]) > eps)
		{
			b[i] -= b[l] * a[i][e];
			for(j = 1 ; j <= n ; j ++ ) if(j != e) a[i][j] -= a[l][j] * a[i][e];
			a[i][e] = -a[l][e] * a[i][e];
		}
	}
	ans += b[l] * c[e];
	for(i = 1 ; i <= n ; i ++ ) if(i != e) c[i] -= c[e] * a[l][i];
	c[e] = -c[e] * a[l][e];
}
void simplex()
{
	int i , l , e;
	double tmp;
	while(1)
	{
		for(i = 1 ; i <= n ; i ++ ) if(c[i] > eps) break;
		if(i > n) break;
		e = i;
		for(i = 1 , tmp = 1e10 ; i <= m ; i ++ )
			if(a[i][e] > eps && b[i] / a[i][e] < tmp)
				l = i , tmp = b[i] / a[i][e];
		if(tmp == 1e10)
		{
			ans = -1;
			break;
		}
		pivot(l , e);
	}
}
int main()
{
	int i , j;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= m ; i ++ )
	{
		for(j = 1 ; j <= n ; j ++ ) scanf("%lf" , &a[i][j]);
		scanf("%lf" , &b[i]);
	}
	for(i = 1 ; i <= n ; i ++ ) scanf("%lf" , &c[i]);
	simplex();
	if(ans != -1) printf("%.2lf\n" , ans);
	else puts("Infinity");
	return 0;
} 

以上为自己总结的板子

希望自己板子别码错,冷静思考,认真答题!

【冲刺noi】真banzi大集合

标签:数据   可并堆   高斯消元   dinic   fail   区间修改   rmi   wap   倍增lca   

原文地址:http://www.cnblogs.com/GXZlegend/p/7189893.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!