Record - Jan. all, 2021 - Training REC

cirnovsky /

∆ P3600 随机数生成器 - AC

记:

w=max{min{alj,alj+1,,arj}j[1,q]}w=\max\{\min\{a_{l_{j}},a_{l_{j}+1},\cdots,a_{r_{j}}\}|j\in[1,q]\}

因为我们最后取的是 max\max,不能直接用全概率公式,转化一下:

E(w)=i=0P(wi)=i=01P(w<i)E(w)=\sum_{i=0}^{\infty}P(w\ge i)=\sum_{i=0}^{\infty}1-P(w<i)

这意味着每一个被询问区间中的最小值都需 <i<i。也就是说,每一个区间至少需要一个 <i<i 的数。

这对于每一个区间来说概率为 i1x\frac{i-1}{x}。又因为区间可能出现相交,所以我们考虑用点去被包含于区间。

当然,一个区间包含另一个区间,这个区间肯定是没有用的。然后把区间按左右端点分别为第一、第二关键字排序。

枚举 ww,设 fif_{i} 表示区间右端点在 ii 之前的所有区间满足条件的概率。

fi=w1x×j=0ifj×(1w1x)ij1f_{i}=\frac{w-1}{x}\times\sum_{j=0}^{i}f_{j}\times(1-\frac{w-1}{x})^{i-j-1}
#include <cstdio>

using i64 = long long;

const int MOD = 666623333;
const int MAXN = 2e3 + 5;

int n, x, q, ar[MAXN];
i64 f[MAXN][2], ff[MAXN][2];

void imax ( int& a, const int b ) { a = a < b ? b : a; }
int add ( const int a, const int b, const int p = MOD ) { return a + b < p ? a + b : ( a + b ) % p; }
int sub ( const int a, const int b, const int p = MOD ) { return a - b < 0 ? a - b + p : a - b; }
int mul ( const i64 a, const i64 b, const int p = MOD ) { return a * b % p; }
int cpow ( int bas, int idx = MOD - 2 ) {
	int res = 1;
	while ( idx ) {
		if ( idx & 1 )	res = mul ( res, bas );
		bas = mul ( bas, bas ), idx >>= 1;
	}
	return res % MOD;
}

int main () {
	scanf ( "%d%d%d", &n, &x, &q );
	for ( int i = 1, tmpl, tmpr; i <= q; ++ i )	scanf ( "%d%d", &tmpl, &tmpr ), imax ( ar[tmpr + 1], tmpl );
	for ( int i = 1; i <= n + 1; ++ i )	imax ( ar[i], ar[i - 1] );
	i64 ix = cpow ( x ), ans = 0;
	for ( int i = 1; i <= x; ++ i ) {
		i64 p = mul ( i - 1, ix ) % MOD, ip = cpow ( 1 - p ), s;
		ff[0][0] = ff[0][1] = 1;
		for ( int j = 1; j <= n; ++ j )	ff[j][0] = mul ( ff[j - 1][0], 1 - p ) % MOD, ff[j][1] = mul ( ff[j - 1][1], ip ) % MOD;
		f[0][0] = 0, f[0][1] = 1;
		for ( int j = 1; j <= n; ++ j ) {
			f[j][0] = mul ( mul ( p, sub ( f[j - 1][1], ar[j] ? f[ar[j] - 1][1] : 0 ) ) % MOD, ff[j - 1][0] ) % MOD;
			f[j][1] = add ( mul ( f[j][0], ff[j][1] ) % MOD, f[j - 1][1] ) % MOD;
		}
		s = 0;
		for ( int j = ar[n + 1]; j <= n; ++ j )	s = add ( s, mul ( f[j][0], ff[n - j][0] ) % MOD ) % MOD;
		ans = sub ( add ( ans, 1 ) % MOD, s );
	}
	printf ( "%lld\n", ans % MOD );
	return 0;
}

∆ P3602 Koishi Loves Segments - AC

依次加入线段(从左到右),然后若有一个点不合删其右端点最远。

#include<bits/stdc++.h>
struct seg{int l,r;bool operator<(seg t){return l<t.l;}}s1[500010],s2[500010];int n,m;std::multiset<int>ms;
int main(){
	std::cin>>n>>m;for(int i=1;i<=n;++i)std::cin>>s1[i].l>>s1[i].r;int ans=0;
	for(int i=1;i<=m;++i)std::cin>>s2[i].l>>s2[i].r;std::sort(s1+1,s1+1+n);std::sort(s2+1,s2+1+m);
	for(int l=1,r=1;l<=m;++l){
		while(r<=n&&s1[r].l<=s2[l].l)ms.insert(s1[r++].r);
		while(ms.size()&&*ms.begin()<s2[l].l)ms.erase(ms.begin());
		while(ms.size()>s2[l].r)ms.erase(std::prev(ms.end())),ans++;
	}std::cout<<n-ans;
}

∆ P4127 [AHOI2009]同类分布 - AC

vector 慢成仙人。

#include <bits/stdc++.h>

using i64 = long long;

i64 a, b, f[20][200][200], ori[20];

i64 dfs ( const int pos, const int sum, const i64 num, const int lim, const int len, const int mod ) {
	if ( ( pos > len && ! sum ) || sum + 9 * len < mod )	return 0;
	if ( pos > len )	return ! num && sum == mod;
	if ( ! lim && ~ f[pos][sum][num] )	return f[pos][sum][num];
	i64 res = 0;
	int mx = lim ? ori[len - pos] : 9;
	for ( int i = 0; i <= mx; ++ i )	res += dfs ( pos + 1, sum + i, ( num * 10 + i ) % mod, lim && i == mx, len, mod );
	return lim ? res : f[pos][sum][num] = res;
}

i64 solve ( const i64 val ) {
	i64 tmp = val;
	int len = 0;
	for ( ; tmp; tmp /= 10 )	ori[len ++] = tmp % 10;
	i64 res = 0;
	for ( int MOD = 1; MOD <= 9 * len; ++ MOD ) {
		memset ( f, -1, sizeof f );
		res += dfs ( 1, 0, 0, 1, len, MOD );
	}
	return res;
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> a >> b;
	std::cout << solve ( b ) - solve ( a - 1 ) << '\n';
	return 0;
}

∆ P3603 雪辉 - AC

疑似是树分块板?

#include <bits/stdc++.h>

using i64 = long long;
using u64 = unsigned long long;

std::mt19937_64 randomEngine ( time ( 0 ) );
int calcRND ( const int  l, const int  r ) {
	std::uniform_int_distribution<long long> distribution ( l, r );
	int randomNumber = distribution ( randomEngine );
	return randomNumber;
}

const int MAXN = 1e5 + 5, MAXS = 330;
const i64 one64 = 1ll;

char gtc () { return getchar (); }
int rint () {
	int x = 0, f = 1; char c = gtc ();
	for ( ; c < '0' || c > '9'; c = gtc () )	f = c == '-' ? -1 : f;
	for ( ; c >= '0' && c <= '9'; c = gtc () )	x = ( x << 3 ) + ( x << 1 ) + ( c & 15 );
	return x * f;
}

void ptc ( const char x ) { putchar ( x ); }
void wint ( int x ) {
	if ( x < 0 )	ptc ( '-' ), x = ~ x + 1;
	if ( x > 9 )	wint ( x / 10 );
	ptc ( x % 10 ^ '0' );
}

template<typename _T> _T imax ( const _T x, const _T y ) { return x < y ? y : x; }
template<typename _T> void swapp ( _T& x, _T& y ) { _T w = x; x = y; y = w; }

struct prBitS {
	u64 c[500]; int L;
	prBitS () : L ( 0 ), c ( { 0 } ) {}
	void clear () { memset ( c, 0, sizeof c ), L = 0; }
	void operator |= ( const prBitS& t ) { L = imax ( L, t.L ); for ( int i = 0; i <= L; ++ i )	c[i] |= t.c[i]; }
	void operator |= ( const int& x ) { L = imax ( L, x >> 6 ); c[x >> 6] |= one64 << ( x & 63 ); }
	int calc_num () {
		int res = 0;
		for ( int i = 0; i <= L; ++ i ) for ( int j = 0; j < 64; ++ j ) {
			if ( c[i] & ( one64 << j ) )	++ res;
		}
		return res;
	}
	int calc_mex () {
		for ( int i = 0; i <= L; ++ i ) for ( int j = 0; j < 64; ++ j ) {
			if ( ! ( c[i] & ( one64 << j ) ) )	return i * 64 + j;
		}
		return 0;
	}
} bs[MAXS][MAXS];

struct Edge { int to, nxt; } graph[MAXN * 2];

int n, m, head[MAXN], ecnt, kfa[MAXN][21], a[MAXN], dep[MAXN], used[MAXN], kSet[MAXN], rk[MAXN], ar[MAXN];

void link ( const int u, const int v ) { graph[++ ecnt] = { v, head[u] }, head[u] = ecnt; }

void dfs ( const int u, const int pr ) {
	dep[u] = dep[pr] + 1, kfa[u][0] = pr;
	for ( int i = 1; i <= 20; ++ i )	kfa[u][i] = kfa[kfa[u][i - 1]][i - 1];
	for ( int i = head[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to;
		if ( v != pr )	dfs ( v, u );
	}
}

int calcLCA ( int u, int v ) {
	if ( dep[u] < dep[v] )	swapp ( u, v );
	for ( int i = 20; ~ i; -- i ) {
		if ( dep[kfa[u][i]] >= dep[v] )	u = kfa[u][i];
	}
	if ( u == v )	return u;
	for ( int i = 20; ~ i; -- i ) {
		if ( kfa[u][i] != kfa[v][i] )	u = kfa[u][i], v = kfa[v][i];
	}
	return kfa[u][0];
}

void initial () {
	int S = sqrt ( n );
	for ( int i = 1; i <= S; ++ i ) {
		int p = calcRND ( 1, n );
		while ( used[p] )	p = calcRND ( 1, n );
		used[p] = 1, kSet[i] = p, rk[p] = i;
	}
	prBitS p_bs;
	for ( int i = 1; i <= S; ++ i ) {
		p_bs.clear ();
		int cur = kSet[i], first = 1;
		while ( cur || first ) {
			p_bs |= a[cur];
			if ( cur != kSet[i] && rk[cur] ) {
				bs[i][rk[cur]] |= p_bs;
				if ( ! ar[kSet[i]] )	ar[kSet[i]] = cur;
			}
			cur = kfa[cur][0];
			first = 0;
		}
	}
}

void jumpAncestors ( int& x, prBitS& ans, const int z ) {
	while ( ! ar[x] && x != z )	ans |= a[x], x = kfa[x][0];
	int cur = x;
	while ( dep[ar[x]] > dep[z] )	x = ar[x];
	ans |= bs[rk[cur]][rk[x]];
	while ( x != z )	ans |= a[x], x = kfa[x][0];
}

int main () {
	n = rint (), m = rint (); int f = rint ();
	for ( int i = 1; i <= n; ++ i )	a[i] = rint ();
	for ( int i = 1; i < n; ++ i ) {
		int u = rint (), v = rint ();
		link ( u, v ), link ( v, u );
	}
	dfs ( 1, 0 ), initial (); int las = 0; prBitS ans;
	for ( int i = 1; i <= m; ++ i ) {
		ans.clear ();
		for ( int T = rint (); T; T -- ) {
			int x = rint (), y = rint ();
			if ( f )	x ^= las, y ^= las;
			int z = calcLCA ( x, y ); ans |= a[z];
			jumpAncestors ( x, ans, z ), jumpAncestors ( y, ans, z );
		}
		int ret_n = ans.calc_num (), ret_m = ans.calc_mex ();
		wint ( ret_n ), ptc ( ' ' ), wint ( ret_m ), ptc ( '\n' );
		las = ret_n + ret_m;
	}
	return 0;
}

∆ LOC3564 最小费用流 - AC

流 板。

#include <bits/stdc++.h>

using i64 = long long;
using pii = std::pair<i64, i64>;

const i64 INF = 1e18;
const int MAXN = 2e5 + 5, MAXM = 2e5 + 5;

i64 rint () {
	i64 x = 0, f = 1; char c = getchar ();
	for ( ; c < '0' || c > '9'; c = getchar () )	f = c == '-' ? -1 : f;
	for ( ; c >= '0' && c <= '9'; c = getchar () )	x = ( x << 3 ) + ( x << 1 ) + ( c & 15 );
	return x * f;
}

template<typename _T> _T imin ( const _T x, const _T y ) { return x < y ? x : y; }

struct Edge { int to, nxt; i64 c, w; } graph[MAXM * 2];

int q[MAXN];

i64 dist[MAXN];
int n, m, head[MAXN], cur[MAXN], ecnt = 1, vis[MAXN], tot;

void link ( const int u, const int v, const i64 c, const i64 w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

bool mkLayer ( const int S, const int T ) {
	int h = 1, t = 0;
	for ( int i = 1; i <= tot; ++ i )	dist[i] = INF, vis[i] = 0;
	dist[q[++ t] = S] = 0, vis[S] = 1;
	while ( h <= t ) {
		int u = q[h ++]; vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	vis[q[++ t] = v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

i64 mkWide ( const int u, const i64 flow, const int T, i64& cst ) {
	if ( u == T )	return flow;
	i64 used = 0; vis[u] = 1;
	for ( int& i = cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
		if ( c && ! vis[v] && dist[v] == dist[u] + w ) {
			i64 ret = mkWide ( v, imin ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	i64 retf = 0, retw = 0;
	while ( mkLayer ( S, T ) ) {
		for ( int i = 1; i <= tot; ++ i )	vis[i] = 0, cur[i] = head[i];
		retf += mkWide ( S, INF, T, retw );
	}
	return { retf, retw };
}

int main () {
	n = rint (), m = rint (); tot = n;
	const int S = 1, T = n;
	for ( int i = 1; i <= m; ++ i ) {
		int u = rint (), v = rint ();
		i64 c = rint (), w = rint ();
		link ( u, v, c, w );
	}
	pii ret = calcMXflow ( S, T );
	printf ( "%lld %lld\n", ret.first, ret.second );
	return 0;
}

∆ LOC3102 网络流 24 题 运输问题

流 板。

#include <bits/stdc++.h>

using i64 = long long;
using pii = std::pair<i64, i64>;

const i64 INF = 1e18;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5, MAXS = 2e3 + 5;

char gtc () { return getchar (); }
void ptc ( const char x ) { putchar ( x ); }

int rint () {
	int x = 0, f = 1; char c = gtc ();
	for ( ; c < '0' || c > '9'; c = gtc () )	f = c == '-' ? -1 : f;
	for ( ; c >= '0' && c <= '9'; c = gtc () )	x = ( x << 3 ) + ( x << 1 ) + ( c & 15 );
	return x * f;
}

template<typename _T> _T imin ( const _T x, const _T y ) { return x < y ? x : y; }

struct Edge { int to, nxt; i64 c, w; } graph[MAXM * 2];

i64 dist[MAXN]; int q[MAXN];
int n, m, head[MAXN], ecnt = 1, cur[MAXN], vis[MAXN], tot;
int arA[MAXN], arB[MAXN], arC[MAXS][MAXS];

void link ( const int u, const int v, const i64 c, const i64 w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

bool mkLayer ( const int S, const int T ) {
	int h = 1, t = 0;
	for ( int i = 1; i <= tot; ++ i )	vis[i] = 0, dist[i] = INF;
	dist[q[++ t] = S] = 0, vis[S] = 1;
	while ( h <= t ) {
		int u = q[h ++]; vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	vis[q[++ t] = v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

i64 mkWide ( const int u, const i64 flow, const int T, i64& cst ) {
	if ( u == T )	return flow;
	i64 used = 0; vis[u] = 1;
	for ( int& i = cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			i64 ret = mkWide ( v, imin ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	i64 retf = 0, retw = 0;
	while ( mkLayer ( S, T ) ) {
		for ( int i = 1; i <= tot; ++ i )	vis[i] = 0, cur[i] = head[i];
		retf += mkWide ( S, INF, T, retw );
	}
	return { retf, retw };
}

void buildEdge ( const int S, const int T, const int f ) {
	memset ( head, 0, sizeof head ), ecnt = 1;
	for ( int i = 1; i <= n; ++ i )	link ( S, i, arA[i], 0 );
	for ( int i = 1; i <= m; ++ i )	link ( i + n, T, arB[i], 0 );
	for ( int i = 1; i <= n; ++ i ) for ( int j = 1; j <= m; ++ j )	link ( i, j + n, INF, f * arC[i][j] );
}

int main () {
	n = rint (), m = rint (); tot = n + m;
	const int S = ++ tot, T = ++ tot;
	for ( int i = 1, c; i <= n; ++ i )	arA[i] = rint ();
	for ( int i = 1, c; i <= m; ++ i )	arB[i] = rint ();
	for ( int i = 1; i <= n; ++ i ) for ( int j = 1; j <= m; ++ j )	arC[i][j] = rint ();
	buildEdge ( S, T, 1 ), printf ( "%lld\n", calcMXflow ( S, T ).second );
	buildEdge ( S, T, -1 ), printf ( "%lld\n", calcMXflow ( S, T ).second * -1 );
	return 0;
}

∆ LOC9382 网络流 24 题 负载平衡问题 - AC

流 板。

#include <bits/stdc++.h>

using pii = std::pair<int, int>;

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;

char gtc () { return getchar (); }
void ptc ( const char x ) { putchar ( x ); }

int rint () {
	int x = 0, f = 1; char c = gtc ();
	for ( ; c < '0' || c > '9'; c = gtc () )	f = c == '-' ? -1 : f;
	for ( ; c >= '0' && c <= '9'; c = gtc () )	x = ( x << 3 ) + ( x << 1 ) + ( c & 15 );
	return x * f;
}

template<typename _T> _T imin ( const _T x, const _T y ) { return x < y ? x : y; }

struct Edge { int to, nxt; int c, w; } graph[MAXM * 2];

int dist[MAXN], all; int q[MAXN];
int n, head[MAXN], cur[MAXN], ecnt = 1, vis[MAXN], tot;

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

bool mkLayer ( const int S, const int T ) {
	int h = 1, t = 0;
	for ( int i = 1; i <= tot; ++ i )	dist[i] = INF, vis[i] = 0;
	dist[q[++ t] = S] = 0, vis[S] = 1;
	while ( h <= t ) {
		int u = q[h ++]; vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to; int c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	vis[q[++ t] = v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to; int c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, imin ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		for ( int i = 1; i <= tot; ++ i )	vis[i] = 0, cur[i] = head[i];
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	n = rint (), tot = n;
	const int S = ++ tot, T = ++ tot;
	for ( int i = 1; i <= n; ++ i ) {
		int c = rint ();
		link ( S, i, c, 0 );
		all += c;
	}
	for ( int i = 1; i <= n; ++ i )	link ( i, i % n + 1, INF, 1 ), link ( i % n + 1, i, INF, 1 );
	for ( int i = 1; i <= n; ++ i )	link ( i, T, all / n, 0 );
	printf ( "%d\n", calcMXflow ( S, T ).second );
	return 0;
} 

∆ LOC3103 网络流 24 题 分配问题 - AC

流 板。

#include <bits/stdc++.h>

using i64 = long long;
using pii = std::pair<i64, i64>;

const i64 INF = 1e18;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5, MAXS = 2e3 + 5;

char gtc () { return getchar (); }
void ptc ( const char x ) { putchar ( x ); }

int rint () {
	int x = 0, f = 1; char c = gtc ();
	for ( ; c < '0' || c > '9'; c = gtc () )	f = c == '-' ? -1 : f;
	for ( ; c >= '0' && c <= '9'; c = gtc () )	x = ( x << 3 ) + ( x << 1 ) + ( c & 15 );
	return x * f;
}

template<typename _T> _T imin ( const _T x, const _T y ) { return x < y ? x : y; }

struct Edge { int to, nxt; i64 c, w; } graph[MAXM * 2];

i64 dist[MAXN]; int q[MAXN];
int n, head[MAXN], cur[MAXN], ecnt = 1, vis[MAXN], tot;
int ar[MAXS][MAXS];

void link ( const int u, const int v, const i64 c, const i64 w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

bool mkLayer ( const int S, const int T ) {
	int h = 1, t = 0;
	for ( int i = 1; i <= tot; ++ i )	dist[i] = INF, vis[i] = 0;
	dist[q[++ t] = S] = 0, vis[S] = 1;
	while ( h <= t ) {
		int u = q[h ++]; vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	vis[q[++ t] = v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

i64 mkWide ( const int u, const i64 flow, const int T, i64& cst ) {
	if ( u == T )	return flow;
	i64 used = 0; vis[u] = 1;
	for ( int& i = cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			i64 ret = mkWide ( v, imin ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	i64 resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		for ( int i = 1; i <= tot; ++ i )	cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

void buildEdge ( const int S, const int T, const int f ) {
	memset ( head, 0, sizeof head ), ecnt = 1;
	for ( int i = 1; i <= n; ++ i )	link ( S, i, 1, 0 );
	for ( int i = 1; i <= n; ++ i )	link ( i + n, T, 1, 0 );
	for ( int i = 1; i <= n; ++ i ) for ( int j = 1; j <= n; ++ j )	link ( i, j + n, 1, f * ar[i][j] );
}

int main () {
	n = rint (), tot = n << 1;
	const int S = ++ tot, T = ++ tot;
	for ( int i = 1; i <= n; ++ i ) for ( int j = 1; j <= n; ++ j )	ar[i][j] = rint ();
	buildEdge ( S, T, 1 ), printf ( "%lld\n", calcMXflow ( S, T ).second );
	buildEdge ( S, T, -1 ), printf ( "%lld\n", calcMXflow ( S, T ).second * -1 );
	return 0;
}

∆ P4068 [SDOI2016]数字配对 - AC

首先我们可以处理出来哪些数字之间可以进行配对。

处理出每一个数的质因子的指数数值和(也就是 a=pici,cia=\prod p_{i}^{c_{i}},\sum c_{i})记为 cnticnt_{i},然后把 cnticnt_{i} 奇数放左边偶数放右边放出二分图。

(S,iL,bi,0),(iR,T,bi,0),(iL,jR,,ci×cj)(S,i\in L,b_{i},0),(i\in R,T,b_{i},0),(i\in L,j\in R,\infty,c_{i}\times c_{j})

负数不管。

fuck everybody here。

#include <bits/stdc++.h>

using i64 = long long;
using pii = std::pair<i64, i64>;

const i64 INF = 1e18;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;

char gtc () { return getchar (); }
void ptc ( const char x ) { putchar ( x ); }

int rint () {
	int x = 0, f = 1; char c = gtc ();
	for ( ; c < '0' || c > '9'; c = gtc () )	f = c == '-' ? -1 : f;
	for ( ; c >= '0' && c <= '9'; c = gtc () )	x = ( x << 3 ) + ( x << 1 ) + ( c & 15 );
	return x * f;
}

template<typename _T> _T imin ( const _T x, const _T y ) { return x < y ? x : y; }

struct Edge { int to, nxt; i64 c, w; } graph[MAXM * 2];

i64 dist[MAXN]; int q[MAXN];
int n, head[MAXN], cur[MAXN], ecnt = 1, vis[MAXN], tot, idx[MAXN];
int arA[MAXN], arB[MAXN], arC[MAXN];

void link ( const int u, const int v, const i64 c, const i64 w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

void mkIdx ( const int x, int& p ) {
	int bk = x;
	for ( int i = 2; i * i <= bk; ++ i ) {
		while ( bk % i == 0 )	p ++, bk /= i;
	}
	if ( bk > 1 )	p ++;
}

bool mkLayer ( const int S, const int T ) {
	int h = 1, t = 0;
	for ( int i = 1; i <= tot; ++ i )	dist[i] = INF, vis[i] = 0;
	dist[q[++ t] = S] = 0, vis[S] = 1;
	while ( h <= t ) {
		int u = q[h ++]; vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	vis[q[++ t] = v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

i64 mkWide ( const int u, const i64 flow, const int T ) {
	if ( u == T )	return flow;
	i64 used = 0; vis[u] = 1;
	for ( int& i = cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			i64 ret = mkWide ( v, imin ( flow - used, c ), T );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

i64 calcMXflow ( const int S, const int T ) {
	i64 c = 0, res = 0, delta;
	while ( mkLayer ( S, T ) ) {
		for ( int i = 1; i <= tot; ++ i )	cur[i] = head[i], vis[i] = 0;
		delta = mkWide ( S, INF, T );
		if ( delta * dist[T] + c > 0 )	return res - c / dist[T];
		res += delta, c += delta * dist[T];
	}
	return res;
}

bool ck ( const int a, const int b ) { return arA[a] % arA[b] == 0 && idx[a] - 1 == idx[b]; }
int main () {
	n = rint (), tot = n;
	const int S = ++ tot, T = ++ tot;
	for ( int i = 1; i <= n; ++ i )	arA[i] = rint (), mkIdx ( arA[i], idx[i] );
	for ( int i = 1; i <= n; ++ i )	arB[i] = rint ();
	for ( int i = 1; i <= n; ++ i )	arC[i] = rint ();
	for ( int i = 1; i <= n; ++ i ) {
		if ( idx[i] & 1 ) {
			link ( S, i, arB[i], 0 );
			for ( int j = 1; j <= n; ++ j ) {
				if ( ck ( i, j ) || ck ( j, i ) )	link ( i, j, INF, -( i64 )arC[i] * arC[j] );
			}
		}
		else	link ( i, T, arB[i], 0 );
	}
	printf ( "%lld\n", calcMXflow ( S, T ) );
	return 0;
}

∆ P2045 方格取数加强版 - AC

水题。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 2e5 + 5;

using pii = std::pair<int, int>;

struct Edge { int to, nxt, c, w; } graph[MAXM * 2];

int n, k, head[MAXN], ecnt = 1, dist[MAXN], vis[MAXN], tot, cur[MAXN];

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

int tr ( const int x, const int y ) { return ( x - 1 ) * n + y; }

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> n >> k; tot = n * n * 2;
	const int S = ++ tot, T = ++ tot;
	link ( S, tr ( 1, 1 ), k, 0 );
	rep ( i, 1, n ) rep ( j, 1, n ) {
		int c; std::cin >> c;
		link ( tr ( i, j ), tr ( i, j ) + n * n, 1, -c );
		link ( tr ( i, j ), tr ( i, j ) + n * n, INF, 0 );
		if ( i < n )	link ( tr ( i, j ) + n * n, tr ( i + 1, j ), INF, 0 );
		if ( j < n )	link ( tr ( i, j ) + n * n, tr ( i, j + 1 ), INF, 0 );
	}
	link ( tr ( n, n ) + n * n, T, k, 0 );
	std::cout << calcMXflow ( S, T ).second * -1 << '\n';
	return 0;
}

∆ LOC5290 网络流 24 题 深海机器人问题 - AC

水题。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;

using pii = std::pair<int, int>;

struct Edge { int to, nxt, c, w; } graph[MAXM * 2];

int pS, pT, n, m, head[MAXN], ecnt = 1, dist[MAXN], vis[MAXN], Cur[MAXN], tot;

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

int tr ( const int x, const int y ) { return ( x - 1 ) * m + y; }

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> pS >> pT >> n >> m; tot = ( ++ n ) * ( ++ m );
	const int S = ++ tot, T = ++ tot;
	rep ( i, 1, n ) rep ( j, 1, m - 1 ) {
		int c; std::cin >> c;
		link ( tr ( i, j ), tr ( i, j + 1 ), 1, -c );
		link ( tr ( i, j ), tr ( i, j + 1 ), INF, 0 );
	}
	rep ( j, 1, m ) rep ( i, 1, n - 1 ) {
		int c; std::cin >> c;
		link ( tr ( i, j ), tr ( i + 1, j ), 1, -c );
		link ( tr ( i, j ), tr ( i + 1, j ), INF, 0 );
	}
	rep ( i, 1, pS ) { int k, x, y;
		std::cin >> k >> x >> y;
		link ( S, tr ( x + 1, y + 1 ), k, 0 );
	}
	rep ( i, 1, pT ) { int k, x, y;
		std::cin >> k >> x >> y;
		link ( tr ( x + 1, y + 1 ), T, k, 0 );
	}
	std::cout << calcMXflow ( S, T ).second * -1 << '\n';
	return 0;
}

∆ LOC5126 网络流 24 题 餐巾计划 - AC

好。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;

using pii = std::pair<int, int>;

struct Edge { int to, nxt, c, w; } graph[MAXM * 2];

int p, m, f, n, s, head[MAXN], ecnt = 1, dist[MAXN], vis[MAXN], tot, Cur[MAXN];

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		if ( dist[T] >= 0 )	break;
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	int days; std::cin >> days; tot = days << 1;
	std::cin >> p >> m >> f >> n >> s;
	const int S = ++ tot, T = ++ tot; int all = 0;
	rep ( i, 1, days ) { int r; std::cin >> r; all += r; link ( S, i, r, 0 ); link ( i + days, T, r, 0 ); }
	rep ( i, 1, days ) {
		if ( i + m <= days )	link ( i, i + days + m, INF, -p + f );
		if ( i + n <= days )	link ( i, i + days + n, INF, -p + s );
		if ( i + 1 <= days )	link ( i + days, i + days + 1, INF, 0 );
	}
	std::cout << calcMXflow ( S, T ).second + all * p << '\n';
	return 0;
}

∆ LOC5127 网络流 24 题 数字梯形 - AC

一般。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

using pii = std::pair<int, int>;

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5, MAXS = 1e3 + 5;

struct Edge { int to, nxt, c, w; } graph[MAXM * 2];

int n, m, head[MAXN], Cur[MAXN], ecnt = 1, dist[MAXN], vis[MAXN], ID[MAXS][MAXS], tot;

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

void irAuged () { for ( int i = 2; i <= ecnt; i += 2 )	graph[i].c += graph[i ^ 1].c, graph[i ^ 1].c = 0; }

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> m >> n; const int exist = ( n + ( m << 1 ) - 1 ) * n >> 1;
	rep ( i, 1, n ) rep ( j, 1, i + m - 1 )	ID[i][j] = ++ tot;
	tot += exist; const int S = ++ tot, T = ++ tot;
	rep ( i, 1, n ) rep ( j, 1, i + m - 1 ) { int c;
		std::cin >> c; link ( ID[i][j], ID[i][j] + exist, 1, -c );
	}
	rep ( i, 1, n - 1 ) rep ( j, 1, i + m - 1 )
		link ( ID[i][j] + exist, ID[i + 1][j], 1, 0 ), link ( ID[i][j] + exist, ID[i + 1][j + 1], 1, 0 );
	rep ( i, 1, m )	link ( S, ID[1][i], 1, 0 );
	rep ( i, 1, n + m - 1 )	link ( ID[n][i] + exist, T, INF, 0 );
	std::cout << calcMXflow ( S, T ).second * -1 << '\n'; irAuged ();
	rep ( i, 1, n ) rep ( j, 1, i + m - 1 ) {
		for ( int k = head[ID[i][j]]; k; k = graph[k].nxt ) {
			int v = graph[k].to; int& c = graph[k].c;
			if ( v == ID[i][j] + exist )	c = INF;
		}
	}
	std::cout << calcMXflow ( S, T ).second * -1 << '\n'; irAuged ();
	rep ( i, 1, n - 1 ) rep ( j, 1, i + m - 1 ) {
		for ( int k = head[ID[i][j] + exist]; k; k = graph[k].nxt ) {
			int v = graph[k].to; int& c = graph[k].c;
			if ( v == ID[i + 1][j] || v == ID[i + 1][j + 1] )	c = INF;
		}
	}
	std::cout << calcMXflow ( S, T ).second * -1 << '\n';
	return 0;
}

∆ P3980 [NOI2008] 志愿者招募 - AC

一个人造成的贡献是一个区间。

然后按时间连边。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

using i64 = long long;
using pii = std::pair<i64, i64>;

const i64 INF = 1e18;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;

struct Edge { int to, nxt; i64 c, w; } graph[MAXM * 2];

i64 dist[MAXN]; bool vis[MAXN];
int n, m, head[MAXN], ecnt = 1, Cur[MAXN], tot;

void link ( const int u, const int v, const i64 c, const i64 w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	for ( int i = 1; i <= tot; ++ i )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

i64 mkWide ( const int u, const i64 flow, const int T, i64& cst ) {
	if ( u == T )	return flow;
	i64 used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			i64 ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	i64 resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> n >> m; tot = n + 1; const int S = ++ tot, T = ++ tot;
	link ( S, 1, n * m, 0 ), link ( n + 1, T, n * m, 0 );
	rep ( i, 1, n ) { int c; std::cin >> c; link ( i, i + 1, n * m - c, 0 ); }
	rep ( i, 1, m ) { int s, t, c;
		std::cin >> s >> t >> c;
		link ( s, t + 1, n * m, c );
	}
	std::cout << calcMXflow ( S, T ).second << '\n';
	return 0;
}

∆ ACW338 计数问题 - AC

水题。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

using i64 = long long;

i64 L, R, f[30][30];
int len, nums[30];

i64 DP ( const int pos, const int lim, const int pre, const int sum, const int aim ) {
	if ( pos > len )	return sum;
	if ( ! pre && ! lim && ~ f[pos][sum] )	return f[pos][sum];
	int mx = lim ? nums[len - pos + 1] : 9; i64 res = 0;
	rep ( i, 0, mx )	res += DP ( pos + 1, lim && i == mx, pre && ! i, sum + ( aim == i && ( i || ( ! i && ! pre ) ) ), aim );
	if ( ! lim && ! pre )	f[pos][sum] = res;
	return res;
}

i64 solve ( const int aim, i64 x ) {
	memset ( f, -1, sizeof f ), len = 0;
	for ( ; x; x /= 10 )	nums[++ len] = x % 10;
	return DP ( 1, 1, 1, 0, aim );
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	while ( std::cin >> L >> R && ! std::cin.eof () ) {
		if ( ! L && ! R )	break;
		if ( L > R )	std::swap ( L, R );
		rep ( i, 0, 9 )	std::cout << solve ( i, R ) - solve ( i, L - 1 ) << ' ';
		std::cout << '\n';
	}
	return 0;
}

∆ BZOJ3329 Xorequ - AC

手化方程,找性质。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

using i64 = long long;

const int MOD = 1e9 + 7;
const int S = 2;

struct Matrix { int c[S + 5][S + 5]; Matrix () { memset ( c, 0, sizeof c ); } } trans;

i64 n, f[100];
int nums[100], len;

int add ( const int a, const int b ) { return a + b < MOD ? a + b : ( a + b ) % MOD; }
int mul ( const i64 a, const i64 b ) { return a * b % MOD; }
Matrix times ( Matrix a, Matrix b ) {
	Matrix res;
	rep ( i, 0, S - 1 ) rep ( j, 0, S - 1 ) rep ( k, 0, S - 1 )
		res.c[i][j] = add ( res.c[i][j], mul ( a.c[i][k], b.c[k][j] ) );
	return res;
}

Matrix cpow ( Matrix bas, i64 idx ) {
	Matrix res;
	rep ( i, 0, S - 1 )	res.c[i][i] = 1;
	while ( idx ) {
		if ( idx & 1 )	res = times ( res, bas );
		bas = times ( bas, bas ), idx >>= 1;
	}
	return res;
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	int T; std::cin >> T;
	f[1] = 1; rep ( i, 2, 64 )	f[i] = f[i - 1] + f[i - 2];
	trans.c[0][0] = trans.c[0][1] = trans.c[1][0] = 1; i64 ans = 0;
	while ( T -- > 0 ) {
		std::cin >> n; len = 0;
		auto tmp = ++ n;
		for ( ; tmp; tmp >>= 1 )	nums[++ len] = tmp & 1;
		nums[len + 1] = ans =0;
		per ( i, len, 1 ) {
			if ( nums[i] )	ans += f[i + 1];
			if ( nums[i] && nums[i + 1] )	break;
		}
		std::cout << ans - 1 << '\n' << cpow ( trans, n ).c[0][0] << '\n';
	}
	return 0;
}

∆ P2053 [SCOI2007]修车 - AC

一个工人拆成各个时间段的,然后肆意连边。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

using pii = std::pair<int, int>;

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 6;

struct Edge { int to, nxt, c, w; } graph[MAXM * 2];

int n, m, head[MAXN], Cur[MAXN], ecnt = 1, dist[MAXN], vis[MAXN], tot;

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

int hs ( const int x, const int y ) { return ( x - 1 ) * n + y; }

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> m >> n; tot = n * m + n;
	const int S = ++ tot, T = ++ tot;
	rep ( j, 1, n ) rep ( i, 1, m ) { int c;
		std::cin >> c; rep ( k, 1, n )	link ( j, hs ( i, k ) + n, 1, c * k );
	}
	rep ( i, 1, n )	link ( S, i, 1, 0 );
	rep ( i, 1, m ) rep ( j, 1, n )	link ( hs ( i, j ) + n, T, 1, 0 );
	std::cout << std::fixed << std::setprecision ( 2 ) << 1.0 * calcMXflow ( S, T ).second / n << '\n';
	return 0;
}

∆ P2153 [SDOI2009]晨跑 - AC

流 板(经 典 重 现)。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

using pii = std::pair<int, int>;

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 6;

struct Edge { int to, nxt, c, w; } graph[MAXM * 2];

int n, m, head[MAXN], Cur[MAXN], ecnt = 1, dist[MAXN], vis[MAXN], tot;

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> n >> m; tot = n << 1;
	rep ( i, 1, m ) { int u, v, c;
		std::cin >> u >> v >> c;
		if ( u == 1 && v == n )	link ( u + n, v, 1, c );
		else	link ( u + n, v, INF, c );
	}
	rep ( i, 1, n )	link ( i, i + n, 1, 0 );
	pii ret = calcMXflow ( n + 1, n );
	std::cout << ret.first << ' ' << ret.second << '\n';
	return 0;
}

∆ P2517 [HAOI2010]订货 - AC

流 板(经 典 再 重 现)。

#include <bits/stdc++.h>

#define rep( x, a, b ) for( int (x) = (a); (x) <= (b); (x) ++ )
#define per( x, a, b ) for( int (x) = (a); (x) >= (b); (x) -- )

using pii = std::pair<int, int>;

const int INF = 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 6;

struct Edge { int to, nxt, c, w; } graph[MAXM * 2];

int n, m, sp, head[MAXN], Cur[MAXN], ecnt = 1, dist[MAXN], vis[MAXN], tot;

void link ( const int u, const int v, const int c, const int w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

int mkWide ( const int u, const int flow, const int T, int& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> n >> m >> sp; tot = n;
	const int S = ++ tot, T = ++ tot;
	rep ( i, 1, n ) { int c; std::cin >> c; link ( i, T, c, 0 ); if ( i < n )	link ( i, i + 1, sp, m ); }
	rep ( i, 1, n ) { int c; std::cin >> c; link ( S, i, INF, c ); }
	std::cout << calcMXflow ( S, T ).second << '\n';
	return 0;
}

∆ AT4994 [AGC034D] Manhattan Max Matching - AC

我神 tm 直接拆曼哈顿距离。

// dist((x1, y1), (x2, y2)) = |x1-x2|+|y1-y2|
//							  max{x1-x2+y1-y2, x2-x1+y1-y2, x1-x2-y1+y2, x2-x1-y1+y2}
//							  max{x1+y1-x2-y2, -x1+y1+x2-y2, x1-y1-x2+y2, -x1-y1+x2+y2}

#include <bits/stdc++.h>

#define rep( x, a, b ) for ( int x = (a); x <= (b); (x) ++ )
#define per( x, a, b ) for ( int x = (a); x >= (b); (x) -- )

using i64 = long long;
using pii = std::pair<int, i64>;

const int INF = 1e9; const i64 INF64 = 1e18;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;

struct Edge { int to, nxt, c; i64 w; } graph[MAXM * 2];

i64 dist[MAXN]; bool vis[MAXN];
int n, head[MAXN], Cur[MAXN], ecnt = 1, tot;

void link ( const int u, const int v, const int c, const i64 w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	rep ( i, 1, tot )	dist[i] = INF64, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to, c = graph[i].c; i64 w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF64;
}

int mkWide ( const int u, const int flow, const int T, i64& cst ) {
	if ( u == T )	return flow;
	int used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to, c = graph[i].c; i64 w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			int ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF64;
	return used;
}

pii calcMXflow ( const int S, const int T ) {
	int resf = 0; i64 resw = 0;
	while ( mkLayer ( S, T ) ) {
		rep ( i, 1, tot )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> n; tot = n << 1; const int S = ++ tot, T = ++ tot;
	const int pa = ++ tot, pb = ++ tot, pc = ++ tot, pd = ++ tot;
	rep ( i, 1, n ) { i64 x, y; int c;
		std::cin >> x >> y >> c;
		link ( S, i, c, 0 );
		link ( i, pa, INF, -( x + y ) );
		link ( i, pb, INF, -( -x + y ) );
		link ( i, pc, INF, -( x - y ) );
		link ( i, pd, INF, -( -x - y ) );
	}
	rep ( i, 1, n ) { i64 x, y; int c;
		std::cin >> x >> y >> c;
		link ( pa, i + n, INF, -( -x - y ) );
		link ( pb, i + n, INF, -( x - y ) );
		link ( pc, i + n, INF, -( -x + y ) );
		link ( pd, i + n, INF, -( x + y ) );
		link ( i + n, T, c, 0 );
	}
	std::cout << calcMXflow ( S, T ).second * -1 << '\n';
	return 0;
}

∆ ARC107F Sum of Abs - AC

niubility.

/*
### disc:
delete -1 1
b[i]>0:a[i]+|b[i]| 2|b[i]| 0
otherwise:a[i]+|b[i]| 0 2|b[i]|

each means cond1.1~3 cond2.1~3

### graph:
(s,i,cond1 or 2.3)
(i',t,cond1 or 2.2)
*/
#include<queue>
#include<cstdio>
using namespace std;
const int INF=1e9;
queue<int>q;
int n,m,s,t;
int head[100010],cur[100010],cntot=1,to[1000010],nxt[1000010],val[1000010],vis[100010],dep[100010],ans,a[100010],b[100010],all;
int myabs(int x)
{
	if(x>0)	return x;
	else	return -x;
}
void addedge(int one,int ano,int lav)
{
	nxt[++cntot]=head[one];
	to[cntot]=ano;
	val[cntot]=lav;
	head[one]=cntot;
	nxt[++cntot]=head[ano];
	to[cntot]=one;
	val[cntot]=0;
	head[ano]=cntot;
}
bool bfs()
{
	for(int i=s;i<=t;++i)
	{
		dep[i]=INF;
		cur[i]=head[i];
		vis[i]=0;
	}
	dep[s]=0;
	vis[s]=1;
	q.push(s);
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		vis[now]=0;
		for(int i=head[now];i;i=nxt[i])
		{
			int y=to[i];
			if(val[i]&&dep[y]>dep[now]+1)
			{
				dep[y]=dep[now]+1;
				if(!vis[y])
				{
					vis[y]=1;
					q.push(y);
				}
			}
		}
	}
	return dep[t]!=INF;
}
int dfs(int x,int lav)
{
	if(x==t)
	{
		ans+=lav;
		return lav;
	}
	int used=0,rlow;
	for(int i=cur[x];i;i=nxt[i])
	{
		cur[x]=i;
		int y=to[i];
		if(val[i]&&dep[y]==dep[x]+1)
		{
			if(rlow=dfs(y,min(lav-used,val[i])))
			{
				val[i]-=rlow;
				val[i^1]+=rlow;
				used+=rlow;
				if(used==lav)	break;
			}
			else	dep[y]=INF;
		}
	}
	return used;
}
int dinic()
{
	ans=0;
	while(bfs())	dfs(s,INF);
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	s=0;
	t=n+n+1;
	for(int i=1;i<=n;++i)	scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)	scanf("%d",&b[i]);
	for(int i=1;i<=m;++i)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u+n,v,INF);
		addedge(v+n,u,INF);
	}
	for(int i=1;i<=n;++i)
	{
		if(b[i]>0)
		{
			addedge(i,i+n,a[i]+myabs(b[i]));
			addedge(s,i,myabs(b[i])<<1);
		}
		else
		{
			addedge(i+n,t,myabs(b[i])<<1);
			addedge(i,i+n,a[i]+myabs(b[i]));
		}
		all+=myabs(b[i]);
	}
	printf("%d\n",all-dinic());
	return 0;
}

∆ ARC111A Simple Math 2 - AC

10NkM2M10NMkM10NMkM10NM(modM)(kZ)\lfloor \frac{10^N - kM^2}{M} \rfloor \equiv \lfloor \frac{10^N}{M} - kM \rfloor \equiv \lfloor \frac{10^N}{M} \rfloor - kM \equiv \lfloor \frac{10^N}{M} \rfloor \pmod M (k \in \mathbb{Z})

#include <iostream>

using i64 = long long;

int cpow ( int bas, i64 idx, const int p ) {
	int res = 1;
	while ( idx ) {
		if ( idx & 1 )	res = ( i64 )res * bas % p;
		bas = ( i64 )bas * bas % p, idx >>= 1;
	}
	return res;
}

int main () {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	i64 n; int m; std::cin >> n >> m;
	std::cout << ( cpow ( 10, n, m * m ) / m ) % m << '\n';
	return 0;
}

∆ P4076 [SDOI2016]墙上的句子 - AC

模拟+网络流。

有点瘤不想写。

#include<map>
#include<set>
#include<queue>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=1e9;
set<string> app;
queue<int> q;
vector<int> e[100010];
vector<string> hstr[110],lstr[110];
map<string,int> mp;
int T,cnt,hang[110],lie[110],n,m,s,t,hway[110],lway[110];
int head[100010],Cur[100010],cntot=1,to[1000010],nxt[1000010],val[1000010],vis[100010],dep[100010],ans,reverans;
char str[110][110];
void addedge(int one,int ano,int lav)
{
	nxt[++cntot]=head[one];
	to[cntot]=ano;
	val[cntot]=lav;
	head[one]=cntot;
	nxt[++cntot]=head[ano];
	to[cntot]=one;
	val[cntot]=0;
	head[ano]=cntot;
}
bool bfs()
{
	for(int i=s;i<=t;++i)
	{
		dep[i]=INF;
		Cur[i]=head[i];
		vis[i]=0;
	}
	dep[s]=0;
	vis[s]=1;
	q.push(s);
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		vis[now]=0;
		for(int i=head[now];i;i=nxt[i])
		{
			int y=to[i];
			if(val[i]&&dep[y]>dep[now]+1)
			{
				dep[y]=dep[now]+1;
				if(!vis[y])
				{
					vis[y]=1;
					q.push(y);
				}
			}
		}
	}
	return dep[t]!=INF;
}
int dfs(int x,int lav)
{
	if(x==t)	return lav;
	int used=0,rlow;
	for(int i=Cur[x];i;i=nxt[i])
	{
		Cur[x]=i;
		int y=to[i];
		if(val[i]&&dep[y]==dep[x]+1)
		{
			if(rlow=dfs(y,min(lav-used,val[i])))
			{
				val[i]-=rlow;
				val[i^1]+=rlow;
				used+=rlow;
				if(used==lav)	break;
			}
			else	dep[y]=INF;
		}
	}
	return used;
}
void dinic()
{
	ans=0;
	while(bfs())	ans+=dfs(s,INF);
}
bool rever(string x)
{
	for(int i=0,j=x.length()-1;i<j;++i,--j)
	{
		if(x[i]!=x[j])	return 0;
	}
	return 1;
}
bool check(string x)
{
	for(int i=0,j=x.length()-1;i<j;++i,--j)
	{
		if(x[i]>x[j])	return 1;
		else if(x[i]<x[j])	return 0;
	}
	return 0;
}
string trans(string x)
{
	if(x.length()==1)	return x;
	else if(x[0]<=x[x.length()-1])	return x;
	else
	{
		for(int i=0,j=x.length()-1;i<j;++i,--j)	swap(x[i],x[j]);
		return x;
	}
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		mp.clear();
		app.clear();
		cnt=reverans=0;
		for(int i=1;i<=n;++i)	scanf("%d",&hang[i]);
		for(int i=1;i<=m;++i)	scanf("%d",&lie[i]);
		for(int i=1;i<=n;++i)	scanf("%s",str[i]+1);
		for(int i=1;i<=n;++i)
		{
			string tmp;
			hstr[i].clear();
			if(hang[i]==1)
			{
				for(int j=1;j<=m;++j)
				{
					if(str[i][j]!='_')	tmp.push_back(str[i][j]);
					else
					{
						if(tmp.size()>=1)	hstr[i].push_back(tmp);
						tmp.clear();
					}
				}
				if(str[i][m]!='_')	hstr[i].push_back(tmp);
			}
			else
			{
				for(int j=m;j>=1;--j)
				{
					if(str[i][j]!='_')	tmp.push_back(str[i][j]);
					else
					{
						if(tmp.size()>=1)	hstr[i].push_back(tmp);
						tmp.clear();
					}
				}
				if(str[i][1]!='_')	hstr[i].push_back(tmp);
			}
		}
		for(int j=1;j<=m;++j)
		{
			string tmp;
			lstr[j].clear();
			if(lie[j]==1)
			{
				for(int i=1;i<=n;++i)
				{
					if(str[i][j]!='_')	tmp.push_back(str[i][j]);
					else
					{
						if(tmp.size()>=1)	lstr[j].push_back(tmp);
						tmp.clear();
					}
				}
				if(str[n][j]!='_')	lstr[j].push_back(tmp);
			}
			else
			{
				for(int i=n;i>=1;--i)
				{
					if(str[i][j]!='_')	tmp.push_back(str[i][j]);
					else
					{
						if(tmp.size()>=1)	lstr[j].push_back(tmp);
						tmp.clear();
					}
				}
				if(str[1][j]!='_')	lstr[j].push_back(tmp);
			}
		}
		for(int i=1;i<=n;++i)
		{
			if(hang[i]==1)
			{
				int way=0;
				for(int j=0;j<hstr[i].size();++j)
				{
					string cur=hstr[i][j];
					if(rever(cur))
					{
						if(!app.count(cur))
						{
							app.insert(cur);
							reverans++;
						}
					}
					else
					{
						if(~way)
						{
							if(check(cur))	hway[i]=1;
							else	hway[i]=0;
							way=-1;
						}
						cur=trans(cur);
						if(!mp[cur])
						{
							mp[cur]=++cnt;
							e[cnt].clear();
						}
						e[mp[cur]].push_back(i);
					}
				}
			}
			else if(hang[i]==-1)
			{
				int way=0;
				for(int j=0;j<hstr[i].size();++j)
				{
					string cur=hstr[i][j];
					if(rever(cur))
					{
						if(!app.count(cur))
						{
							app.insert(cur);
							reverans++;
						}
					}
					else
					{
						if(~way)
						{
							if(check(cur))	hway[i]=1;
							else	hway[i]=0;
							way=-1;
						}
						cur=trans(cur);
						if(!mp[cur])
						{
							mp[cur]=++cnt;
							e[cnt].clear();
						}
						e[mp[cur]].push_back(i);
					}
				}
			}
			else
			{
				for(int j=0;j<hstr[i].size();++j)
				{
					string cur=hstr[i][j];
					if(rever(cur))
					{
						if(!app.count(cur))
						{
							app.insert(cur);
							reverans++;
						}
					}
					else
					{
						cur=trans(cur);
						if(!mp[cur])
						{
							mp[cur]=++cnt;
							e[cnt].clear();
						}
						e[mp[cur]].push_back(i);
					}
				}
				hway[i]=-1;
			}
		}
		for(int j=1;j<=m;++j)
		{
			if(lie[j]==1)
			{
				int way=0;
				for(int i=0;i<lstr[j].size();++i)
				{
					string cur=lstr[j][i];
					if(rever(cur))
					{
						if(!app.count(cur))
						{
							app.insert(cur);
							reverans++;
						}
					}
					else
					{
						if(~way)
						{
							if(check(cur))	lway[j]=1;
							else	lway[j]=0;
							way=-1;
						}
						cur=trans(cur);
						if(!mp[cur])
						{
							mp[cur]=++cnt;
							e[cnt].clear();
						}
						e[mp[cur]].push_back(j+n);
					}
				}
			}
			else if(lie[j]==-1)
			{
				int way=0;
				for(int i=0;i<lstr[j].size();++i)
				{
					string cur=lstr[j][i];
					if(rever(cur))
					{
						if(!app.count(cur))
						{
							app.insert(cur);
							reverans++;
						}
					}
					else
					{
						if(~way)
						{
							if(check(cur))	lway[j]=1;
							else	lway[j]=0;
							way=-1;
						}
						cur=trans(cur);
						if(!mp[cur])
						{
							mp[cur]=++cnt;
							e[cnt].clear();
						}
						e[mp[cur]].push_back(j+n);
					}
				}
			}
			else
			{
				for(int i=0;i<lstr[j].size();++i)
				{
					string cur=lstr[j][i];
					if(rever(cur))
					{
						if(!app.count(cur))
						{
							app.insert(cur);
							reverans++;
						}
					}
					else
					{
						cur=trans(cur);
						if(!mp[cur])
						{
							mp[cur]=++cnt;
							e[cnt].clear();
						}
						e[mp[cur]].push_back(j+n);
					}
				}
				lway[j]=-1;
			}
		}
		s=0;
		t=n+m+cnt+cnt+1;
		for(int i=s;i<=t;++i)	head[i]=0;
		cntot=1;
		for(int i=1;i<=n;++i)
		{
			if(hway[i]==0)	addedge(s,i,INF);
			else if(hway[i]==1)	addedge(i,t,INF);
		}
		for(int j=1;j<=m;++j)
		{
			if(lway[j]==0)	addedge(s,j+n,INF);
			else if(lway[j]==1)	addedge(j+n,t,INF);
		}
		for(int i=1;i<=cnt;++i)
		{
			addedge(s,i+n+m,1);
			addedge(i+cnt+n+m,t,1);
			for(int j=0;j<e[i].size();++j)
			{
				addedge(i+n+m,e[i][j],INF);
				addedge(e[i][j],i+cnt+n+m,INF);
			}
		}
		dinic();
		printf("%d\n",((ans-cnt)<<1)+reverans);
	}
	return 0;
}

∆ P4716 【模板】最小树形图 - AC

板题,不过我拿 tarjan 实现好像没有优越性……

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=1e9;
vector<pair<int,long long> > e[2][110];
int n,m,root,belong[110],col,val[2][110],pre[2][110],dfn[110],low[110],cnt,sta[110],top,siz[110];
void tarjan(int x,int r)
{
	dfn[x]=low[x]=++cnt;
	sta[++top]=x;
	int y=pre[r][x];
	if(y)
	{
		if(!dfn[y])
		{
			tarjan(y,r);
			low[x]=min(low[x],low[y]);
		}
		else if(!belong[y])	low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x])
	{
		belong[x]=++col;
		siz[col]=1;
		while(sta[top]!=x)
		{
			belong[sta[top--]]=col;
			siz[col]++;
		}
		top--;
	}
}
long long solve()
{
	int turn=0;
	long long res=0;
	while(233)
	{
		cnt=col=0;
		for(int i=1;i<=n;++i)	dfn[i]=belong[i]=0;
		for(int i=1;i<=n;++i)
		{
			if(!dfn[i])	tarjan(i,turn);
		}
		for(int i=1;i<=n;++i)
		{
			if(i!=root&&val[turn][i]==INF)	return -1;
		}
		if(col==n)
		{
			for(int i=1;i<=n;++i)
			{
				if(i!=root)	res+=val[turn][i];
			}
			return res;
		}
		for(int i=1;i<=n;++i)
		{
			if(belong[pre[turn][i]]==belong[i])	res+=val[turn][i];
		}
		for(int i=1;i<=n;++i)
		{
			e[turn^1][i].clear();
			val[turn^1][i]=INF;
			pre[turn^1][i]=0;
		}
		for(int i=1;i<=n;++i)
		{
			for(int j=0;j<e[turn][i].size();++j)
			{
				int y=e[turn][i][j].first;
				long long z=e[turn][i][j].second;
				if(belong[i]!=belong[y])
				{
					if(siz[belong[y]]>1)	z-=val[turn][y];
					e[turn^1][belong[i]].push_back(make_pair(belong[y],z));
					if(z<val[turn^1][belong[y]])
					{
						val[turn^1][belong[y]]=z;
						pre[turn^1][belong[y]]=belong[i];
					}
				}
			}
		}
		n=col;
		root=belong[root];
		turn^=1;
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&root);
	for(int i=1;i<=n;++i)	val[0][i]=INF;
	for(int i=1;i<=m;++i)
	{
		int u,v;
		long long w;
		scanf("%d%d%lld",&u,&v,&w);
		if(u!=v&&v!=root)
		{
			e[0][u].push_back(make_pair(v,w));
			if(val[0][v]>w)
			{
				val[0][v]=w;
				pre[0][v]=u;
			}
		}
	}
	printf("%lld\n",solve());
	return 0;
}

∆ BZOJ2481 PKU3164 Command Network - AC

....

#include<cmath>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=1e9;
int n,m,root,belong[1010],col,pre[2][1010],val[2][1010],dfn[1010],low[1010],cnt,sta[1010],top,siz[1010];
int head[2][1010],nxt[2][1000010],to[2][1000010],cntot[2];
long long X[1010],Y[1010],lav[2][1000010];
void addedge(int one,int ano,long long tak,int id)
{
	to[id][++cntot[id]]=ano;
	lav[id][cntot[id]]=tak;
	nxt[id][cntot[id]]=head[id][one];
	head[id][one]=cntot[id];
}
void tarjan(int x,int p)
{
	dfn[x]=low[x]=++cnt;
	sta[++top]=x;
	int y=pre[p][x];
	if(y)
	{
		if(!dfn[y])
		{
			tarjan(y,p);
			low[x]=min(low[x],low[y]);
		}
		else if(!belong[y])	low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x])
	{
		belong[x]=++col;
		siz[col]=1;
		while(sta[top]!=x)
		{
			belong[sta[top--]]=col;
			siz[col]++;
		}
		top--;
	}
}
long long solve()
{
	int turn=0;
	long long res=0;
	while(233)
	{
		cnt=col=0;
		for(int i=1;i<=n;++i)	dfn[i]=belong[i]=0;
		for(int i=1;i<=n;++i)
		{
			if(!dfn[i])	tarjan(i,turn);
		}
		if(col==n)
		{
			for(int i=1;i<=n;++i)
			{
				if(i!=root)	res+=val[turn][i];
			}
			return res;
		}
		for(int i=1;i<=n;++i)
		{
			if(belong[pre[turn][i]]==belong[i])	res+=val[turn][i];
		}
		cntot[turn^1]=0;
		for(int i=1;i<=col;++i)
		{
			head[turn^1][i]=0;
			val[turn^1][i]=INF;
			pre[turn^1][i]=0;
		}
		for(int i=1;i<=n;++i)
		{
			for(int j=head[turn][i];j;j=nxt[turn][j])
			{
				int y=to[turn][j];
				long long z=lav[turn][j];
				if(belong[i]^belong[y])
				{
					if(siz[belong[y]]>1)	z-=val[turn][y];
					addedge(belong[i],belong[y],z,turn^1);
					if(z<val[turn^1][belong[y]])
					{
						val[turn^1][belong[y]]=z;
						pre[turn^1][belong[y]]=belong[i];
					}
				}
			}
		}
		n=col;
		root=belong[root];
		turn^=1;
	}
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		root=++n;
		for(int i=1;i<n;++i)	scanf("%lld%lld",&X[i],&Y[i]);
		cntot[0]=0;
		for(int i=1;i<=n;++i)
		{
			head[0][i]=0;
			val[0][i]=INF;
			pre[0][i]=0;
		}
		for(int i=1;i<n;++i)
		{
			addedge(n,i,INF,0);
			pre[0][i]=n;
			val[0][i]=INF;
		}
		for(int i=1;i<=m;++i)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			if(u^v)
			{
				long long w=abs(X[u]-X[v])+abs(Y[u]-Y[v]);
				addedge(u,v,w,0);
				if(w<val[0][v])
				{
					val[0][v]=w;
					pre[0][v]=u;
				}
			}
		}
		long long ret=solve();
		if(ret>=(INF<<1))	printf("Poor\n");
		else	printf("%lld\n",ret-INF);
	}
	return 0;
}

∆ BZOJ4349 最小树形图 / P2792 [JSOI2008]小店购物 - AC

拆点跑最小树形图。

#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=1e9;
int n,m,k,root,pre[2][6010],cnt,sta[6010],top,head[2][6010],to[2][1000010],nxt[2][1000010],b[60],ID[60][110],cntot[2],belong[6010],col,siz[6010],dfn[6010],low[6010];
double lav[2][1000010],val[2][6010],a[60];
void addedge(int one,int ano,double hav,int id)
{
	to[id][++cntot[id]]=ano;
	nxt[id][cntot[id]]=head[id][one];
	lav[id][cntot[id]]=hav;
	head[id][one]=cntot[id];
}
void tarjan(int x,int ed)
{
	dfn[x]=low[x]=++cnt;
	sta[++top]=x;
	int y=pre[ed][x];
	if(y)
	{
		if(!dfn[y])
		{
			tarjan(y,ed);
			low[x]=min(low[x],low[y]);
		}
		else if(!belong[y])	low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x])
	{
		belong[x]=++col;
		siz[col]=1;
		while(sta[top]^x)
		{
			belong[sta[top--]]=col;
			siz[col]++;
		}
		top--;
	}
}
double solve()
{
	int turn=0;
	double res=0;
	while(233)
	{
		cnt=col=0;
		for(int i=1;i<=n;++i)	dfn[i]=belong[i]=0;
		for(int i=1;i<=n;++i)
		{
			if(!dfn[i])	tarjan(i,turn);
		}
		if(col==n)
		{
			for(int i=1;i<=n;++i)
			{
				if(i^root)	res+=val[turn][i];
			}
			return res;
		}
		for(int i=1;i<=n;++i)
		{
			if(belong[pre[turn][i]]==belong[i])	res+=val[turn][i];
		}
		cntot[turn^1]=0;
		for(int i=1;i<=n;++i)
		{
			head[turn^1][i]=0;
			val[turn^1][i]=INF;
			pre[turn^1][i]=0;
		}
		for(int i=1;i<=n;++i)
		{
			for(int j=head[turn][i];j;j=nxt[turn][j])
			{
				int y=to[turn][j];
				double z=lav[turn][j];
				if(belong[i]^belong[y])
				{
					if(siz[belong[y]]>1)	z-=val[turn][y];
					addedge(belong[i],belong[y],z,turn^1);
					if(val[turn^1][belong[y]]>z)
					{
						val[turn^1][belong[y]]=z;
						pre[turn^1][belong[y]]=belong[i];
					}
				}
			}
		}
		n=col;
		root=belong[root];
		turn^=1;
	}
}
int main()
{
	scanf("%d",&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%lf%d",&a[i],&b[i]);
		for(int j=1;j<=b[i];++j)
		{
			ID[i][j]=++n;
			val[0][n]=INF;
		}
	}
	val[0][++n]=INF;
	root=n;
	for(int i=1;i<=m;++i)
	{
		if(b[i])
		{
			addedge(root,ID[i][1],a[i],0);
			val[0][ID[i][1]]=a[i];
			pre[0][ID[i][1]]=root;
			for(int j=2;j<=b[i];++j)
			{
				addedge(ID[i][j-1],ID[i][j],a[i],0);
				val[0][ID[i][j]]=a[i];
				pre[0][ID[i][j]]=ID[i][j-1];
			}
		}
	}
	scanf("%d",&k);
	for(int i=1;i<=k;++i)
	{
		int u,v;
		double w;
		scanf("%d%d%lf",&u,&v,&w);
		if(u^v)
		{
			for(int j=1;j<=b[v];++j)
			{
				addedge(ID[u][1],ID[v][j],w,0);
				if(val[0][ID[v][j]]>w)
				{
					val[0][ID[v][j]]=w;
					pre[0][ID[v][j]]=ID[u][1];
				}
			}
		}
	}
	printf("%.2lf\n",solve());
	return 0;
}

∆ P2573 [SCOI2012]滑雪与时间胶囊 - AC

一道在 最小树形图 链接里 且 不能用其过的题。

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
vector<pair<long long,long long> > e[100010];
long long n,m,h[100010],fa[100010],oneans,anoans,vis[100010];
struct edge
{
	long long fr,ba,val;
}lin[2000010];
void makeset()
{
	for(long long i=1;i<=n;++i)	fa[i]=i;
}
long long findset(long long x)
{
	if(x^fa[x])	fa[x]=findset(fa[x]);
	return fa[x];
}
bool mergeset(long long x,long long y)
{
	x=findset(x);
	y=findset(y);
	if(x^y)
	{
		fa[x]=y;
		return 1;
	}
	else	return 0;
}
void dfs(long long x)
{
	vis[x]=1;
	++oneans;
	for(long long i=0;i<e[x].size();++i)
	{
		long long y=e[x][i].first,z=e[x][i].second;
		lin[++m].fr=x;
		lin[m].ba=y;
		lin[m].val=z;
		if(!vis[y])	dfs(y);
	}
}
bool cmp(edge one,edge ano)
{
	if(h[one.ba]^h[ano.ba])	return h[one.ba]>h[ano.ba];
	else	return one.val<ano.val;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	makeset();
	for(long long i=1;i<=n;++i)	scanf("%lld",&h[i]);
	for(long long i=1;i<=m;++i)
	{
		long long u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		if(h[u]>=h[v])	e[u].push_back(make_pair(v,w));
		if(h[u]<=h[v])	e[v].push_back(make_pair(u,w));
	}
	m=0;
	dfs(1);
	sort(lin+1,lin+1+m,cmp);
	long long tmp=oneans;
	for(long long i=1;i<=m;++i)
	{
		if(mergeset(lin[i].fr,lin[i].ba))
		{
			anoans+=lin[i].val;
			--tmp;
			if(tmp<2)	break;
		}
	}
	printf("%lld %lld\n",oneans,anoans);
	return 0;
}

∆ ARC111B Reversible Cards - AC

nowcoder 原题。

#include<cstdio>
int n,cab[400010],fa[400010],a,b,ans;
int findset(int x)
{
	if(fa[x])	return fa[x]=findset(fa[x]);
	else	return x;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%d%d",&a,&b);
		a=findset(a);
		b=findset(b);
		if((a^b)&&(!cab[a]||!cab[b]))
		{
			fa[a]=b;
			cab[b]|=cab[a];
			ans++;
		}
		else if(!cab[a])
		{
			cab[a]=1;
			ans++;
		}
	}
	printf("%d\n",ans);
	return 0;
}

∆ ARC111C Too Heavy - AC

构造出一个操作序列。

先不考虑最小,只考虑构造出来。

参考某道 ABC D 题,直接连边。

ipippiii\rightarrow p_{i}\rightarrow p_{p_{i}}\rightarrow\cdots\rightarrow i

craft.png

1 21\ 2 分别表示 person、baggage。

再想,相当于我们想要让,11 and 22 一一对应。

一个 (u,v)(u,v)22(即 vv)不能被交换只在 aubva_{u}\le b_{v}

所以无解就是这个环中存在 aubva_{u}\le b_{v}

剩下构造,先考虑满足规则。

贪心的选一个最大的 aia_{i} 进行即可。

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
vector<pair<int,int> > ans;
int n,a[200010],b[200010],p[200010],rev[200010],vis[200010];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)	scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)	scanf("%d",&b[i]);
	for(int i=1;i<=n;++i)
	{
		scanf("%d",&p[i]);
		rev[p[i]]=i;
	}
	vector<int> per;
	for(int i=1;i<=n;++i)
	{
		if(p[i]^i)
		{
			if(a[rev[i]]<=b[i])
			{
				printf("-1\n");
				return 0;
			}
			if(!vis[i])
			{
				vis[i]=1;
				per.clear();
				per.push_back(i);
				for(int j=p[i];j^i;j=p[j])
				{
					if(a[rev[j]]<=b[j])
					{
						printf("-1\n");
						return 0;
					}
					vis[j]=1;
					per.push_back(j);
				}
				int pos=0,val=0;
				for(int j=0;j<per.size();++j)
				{
					if(a[per[pos]]<=a[per[j]])
					{
						pos=j;
						val=per[j];
					}
				}
				for(int j=pos+1;j<per.size();++j)	ans.push_back(make_pair(val,per[j]));
				for(int j=0;j<pos;++j)	ans.push_back(make_pair(val,per[j]));
			}
		}
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();++i)	printf("%d %d\n",ans[i].first,ans[i].second);
	return 0;
}

∆ SYZOJ725 吃火锅 - AC

状压。

#include<cstdio>
const int mod=1e6+7;
int n,m,f[20][(1<<12)+10],eve[20],upp,st[(1<<12)+10],top,ans;
int main()
{
	scanf("%d%d",&n,&m);
	upp=1<<m;
	for(int i=0;i<n;++i)
	{
		for(int j=0;j<m;++j)
		{
			int x;
			scanf("%d",&x);
			eve[i]^=(x^1)<<j;
		}
	}
	for(int i=0;i^upp;++i)
	{
		if(!(i&(i<<1)))	st[top++]=i;
	}
	for(int i=0;i<top;++i)
	{
		if(!(eve[0]&st[i]))	f[0][i]=1;
	}
	for(int i=1;i<n;++i)
	{
		for(int j=0;j<top;++j)
		{
			if(f[i-1][j])
			{
				for(int k=0;k<top;++k)
				{
					if(!(eve[i]&st[k])&&!(st[j]&st[k]))	f[i][k]=(f[i][k]+f[i-1][j])%mod;
				}
			}
		}
	}
	for(int i=0;i<top;++i)	ans=(ans+f[n-1][i])%mod;
	printf("%d\n",ans);
	return 0;
}

∆ ARC111D Orientation - AC

像个贪心?

  • cucvc_{u}\neq c_{v}

    • cu>cvc_{u}>c_{v}\rightarrow
    • cu<cvc_{u}<c_{v}\leftarrow
  • cu=cvc_{u}=c_{v}

在一个环里,深搜即可。

这 C D 放反了吧

#include<queue>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
vector<pair<int,int> > e[110];
vector<string> ans;
int n,m,c[110],eve[110][110],vis[110];
void dfs(int x)
{
	vis[x]=1;
	for(int i=1;i<=n;++i)
	{
		if(eve[x][i])
		{
			eve[i][x]=0;
			if(!vis[i])	dfs(i);
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		e[u].push_back(make_pair(v,i));
	}
	for(int i=1;i<=n;++i)	scanf("%d",&c[i]);
	ans.resize(m);
	for(int i=1;i<=n;++i)
	{
		for(int j=0;j<e[i].size();++j)
		{
			int y=e[i][j].first,id=e[i][j].second-1;
			if(c[i]>c[y])	ans[id]="->";
			else if(c[i]<c[y])	ans[id]="<-";
			else	eve[i][y]=eve[y][i]=1;
		}
	}
	for(int i=1;i<=n;++i)
	{
		for(int j=0;j<e[i].size();++j)
		{
			int y=e[i][j].first,id=e[i][j].second-1;
			dfs(i);
			if(eve[i][y])	ans[id]="->";
			else if(eve[y][i])	ans[id]="<-";
		}
	}
	for(int i=0;i<ans.size();++i)	printf("%s\n",ans[i].c_str());
	return 0;
}

∆ AT5141 [AGC035D] Add and Remove - AC

答案一定是最后的 a1+ana_{1}+a_{n}。按照贡献来考虑的话,这俩数只对答案贡献一次。

考虑两个数 ai,ai+1a_{i},a_{i+1} 之间插入一个数,那么这个数会对答案贡献 ci+ci+1c_{i}+c_{i+1} 次(cc 表示某个元素的贡献次数)。

想想状态数,能做了:

fl,r,cl,crf_{l,r,c_{l},c_{r}} 为不用说的状态,转移看心情写。

#include<cstdio>
#include<algorithm>
using namespace std;
long long a[30];
int n;
long long dfs(int l,int r,int one,int ano)
{
	if(l+1<r)
	{
		long long res=1e18;
		for(int i=l+1;i<r;++i)	res=min(res,dfs(l,i,one,one+ano)+dfs(i,r,one+ano,ano)+a[i]*(one+ano));
		return res;
	}
	else	return 0;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)	scanf("%lld\n",&a[i]);
	printf("%lld\n",a[1]+a[n]+dfs(1,n,1,1));
	return 0;
}

∆ ARC111E Simple Math 3 - AC

即求:

i=1[A+B×i1D=A+C×iD]\sum_{i=1}^{\infty}[\lfloor\frac{A+B\times i-1}{D}\rfloor=\lfloor\frac{A+C\times i}{D}\rfloor]

题目说这玩意儿是 finite,然后(没加思考)跑到 U 群问成功丢人。

悲伤的故事,这告诉我们问前先思考。

原因是 ii 大了 [A+B×i,A+C×i][A+B\times i,A+C\times i] 的长度一定 D\ge D

具体来说是 i>D2CBi>\frac{D-2}{C-B} 的时候就完了。

那么式子改写为:

i=1D2CB[A+B×i1D=A+C×iD]\sum_{i=1}^{\frac{D-2}{C-B}}[\lfloor\frac{A+B\times i-1}{D}\rfloor=\lfloor\frac{A+C\times i}{D}\rfloor]

继续分析,此时的区间 [A+B×i,A+C×i][A+B\times i,A+C\times i] 的长度小于 DD,里面最多有一个数是 DD 的 multiple。

不会了 看题解 要类欧 不会了 抄板子 过题了

这种推不复杂考板的题好草人啊。。。。

upd:

official editorial 说可以用 AC lib 的 floor_sum 直接算。

屑行为 details

#include<cstdio>
int T;
long long a,b,c,d;
long long dfs(long long a,long long b,long long c,long long n)
{
	if(a>=c||b>=c)	return dfs(a%c,b%c,c,n)+(a/c)*(n+1)*n/2+(b/c)*(n+1);
	else if(a==0)	return 0;
	else	return (a*n+b)/c*n-dfs(c,c-b-1,a,(a*n+b)/c-1);
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
		printf("%lld\n",(d-2)/(c-b)-dfs(c,a,d,(d-2)/(c-b))+dfs(b,a-1,d,(d-2)/(c-b)));
	}
	return 0;
}

∆ P5544 [JSOI2016]炸弹攻击1 - AC

模拟退火板。。。

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const double final=1e-9,delta=0.996,begip=23333,alpha=1215;
int n,m,R,X[20],Y[20],r[20],p[1010],q[1010],ans;
double ansx,ansy;
double dist(double onex,double oney,double anox,double anoy)
{
	return sqrt((onex-anox)*(onex-anox)+(oney-anoy)*(oney-anoy));
}
int f(double x,double y)
{
	double cur=R;
	for(int i=1;i<=n;++i)	cur=min(cur,dist(x,y,X[i],Y[i])-r[i]);
	int res=0;
	for(int i=1;i<=m;++i)
	{
		if(dist(x,y,p[i],q[i])<cur)	res++;
	}
	return res;
}
void find()
{
	double tem=begip;
	int temans=0;
	while(tem>final)
	{
		double nowx=ansx+((rand()<<1)-RAND_MAX)*tem;
		double nowy=ansy+((rand()<<1)-RAND_MAX)*tem;
		int nowans=f(nowx,nowy);
		if(nowans-temans>0)
		{
			temans=nowans;
			ansx=nowx;
			ansy=nowy;
			ans=max(ans,temans);
		}
		else if(exp((nowans-temans)/sqrt(tem))>(double)rand()/alpha)
		{
			ansx=nowx;
			ansy=nowy;
			temans=nowans;
		}
		tem*=delta;
	}
}
int main()
{
    srand(time(0));
	scanf("%d%d%d",&n,&m,&R);
	for(int i=1;i<=n;++i)	scanf("%d%d%d",&X[i],&Y[i],&r[i]);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d",&p[i],&q[i]);
		ansx+=p[i];
		ansy+=q[i];
	}
	ansx/=m;
	ansy/=m;
	ans=f(ansx,ansy);
	for(int i=1;i<=8;++i)	find();
	printf("%d\n",ans);
	return 0;
}

∆ P2495 [SDOI2011]消耗战 - AC

虚树 DP。

/*
VIOLENCE:
dp[u] - cut the keys in subtree(u)
if v is a key:
	dp[u]=dp[u]+w(u,v)
else:
	dp[u]=dp[u]+min(dp[v],w(u,v))
*/
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const long long INF=1e15;
vector<pair<long long,long long> > e[300010];
long long n,m,dis[300010],key[300010],k,dp[300010],sta[300010],top,dfn[300010],cnt;
long long fa[300010][21],val[300010][21],dep[300010],h[300010],power[300010];
bool cmp(long long one,long long ano)
{
	return dfn[one]<dfn[ano];
}
void dfs(long long x,long long las,long long co)
{
	dfn[x]=++cnt;
	dep[x]=dep[las]+1;
	fa[x][0]=las;
	val[x][0]=co;
	for(long long i=1;i^21;++i)
	{
		fa[x][i]=fa[fa[x][i-1]][i-1];
		val[x][i]=min(val[x][i-1],val[fa[x][i-1]][i-1]);
	}
	for(long long i=0;i<e[x].size();++i)
	{
		long long y=e[x][i].first,z=e[x][i].second;
		if(y^las)	dfs(y,x,z);
	}
}
long long LCA(long long one,long long ano)
{
	if(dep[one]<dep[ano])	swap(one,ano);
	for(long long i=20;~i;--i)
	{
		if(dep[fa[one][i]]>=dep[ano])	one=fa[one][i];
	}
	if(one^ano)
	{
		for(long long i=20;~i;--i)
		{
			if(fa[one][i]^fa[ano][i])
			{
				one=fa[one][i];
				ano=fa[ano][i];
			}
		}
		return fa[one][0];
	}
	else	return one;
}
long long getmin(long long one,long long ano)
{
	long long res=INF;
	if(dep[one]<dep[ano])	swap(one,ano);
	for(long long i=20;~i;--i)
	{
		if(dep[fa[one][i]]>dep[ano])
		{
			res=min(res,val[one][i]);
			one=fa[one][i];
		}
	}
	return min(res,val[one][0]);
}
void build()
{
	sort(h+1,h+k+1,cmp);
	power[sta[top=1]=1]=0;
	e[1].clear();
	for(long long i=(h[1]==1?2:1);i<=k;++i)
	{
		long long anc=LCA(h[i],sta[top]);
		if(anc^sta[top])
		{
			while(dfn[anc]<dfn[sta[top-1]])
			{
				e[sta[top-1]].push_back(make_pair(sta[top],getmin(sta[top-1],sta[top])));
				top--;
			}
			if(dfn[anc]==dfn[sta[top-1]])
			{
				e[anc].push_back(make_pair(sta[top],getmin(anc,sta[top])));
				top--;
			}
			else
			{
				e[anc].clear();
				power[anc]=0;
				e[anc].push_back(make_pair(sta[top],getmin(anc,sta[top])));
				sta[top]=anc;
			}
		}
		e[h[i]].clear();
		sta[++top]=h[i];
		power[h[i]]=1;
	}
	while(top>1)
	{
		e[sta[top-1]].push_back(make_pair(sta[top],getmin(sta[top-1],sta[top])));
		top--;
	}
}
void exdfs(long long x)
{
	long long val=0;
	for(long long i=0;i<e[x].size();++i)
	{
		long long y=e[x][i].first,z=e[x][i].second;
		if(power[y])	val+=z;
		else
		{
			dp[y]=min(dp[x],z);
			exdfs(y);
			val+=dp[y];
		}
	}
	dp[x]=min(dp[x],val);
}
int main()
{
	scanf("%lld",&n);
	for(long long i=1;i<n;++i)
	{
		long long u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		e[u].push_back(make_pair(v,w));
		e[v].push_back(make_pair(u,w));
	}
	dfs(1,1,0);
	scanf("%lld",&m);
	for(long long i=1;i<=m;++i)
	{
		scanf("%lld",&k);
		for(long long j=1;j<=k;++j)	scanf("%lld",&h[j]);
		build();
		dp[1]=INF;
		exdfs(1);
		printf("%lld\n",dp[1]);
	}
	return 0;
}

∆ P4103 [HEOI2014]大工程 - AC

虚树 DP 大码量。

/*
(u,v)
siz[u] - how many keys are there in subtree(u)
dep[u] - the depth of u

# first
	(u,v) will be counted for (k-siz[v])*siz[v] times
	then its contribution is (dep[v]-dep[u])*(k-siz[v])*siz[v]

# second
	f[u][0/1] - how far is it from the nearest/second nearest key in subtree(u) to u

# third
	same as second
*/
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const long long INF=1e9;
vector<pair<long long,long long> > e[1000010];
long long n,m,k,sta[1000010],top,power[1000010],dep[1000010],fa[1000010][21],val[1000010][21],h[1000010],siz[1000010],dfn[1000010],cnt;
long long onemxlen[1000010],anomxlen[1000010],onemnlen[1000010],anomnlen[1000010],ans,oneans,anoans;
void dfs(long long x,long long las)
{
	dfn[x]=++cnt;
	dep[x]=dep[las]+1;
	fa[x][0]=las;
	for(long long i=1;i<=20;++i)	fa[x][i]=fa[fa[x][i-1]][i-1];
	for(long long i=0;i<e[x].size();++i)
	{
		long long y=e[x][i].first;
		if(y^las)	dfs(y,x);
	}
}
long long LCA(long long one,long long ano)
{
	if(dep[one]<dep[ano])	swap(one,ano);
	for(long long i=20;~i;--i)
	{
		if(dep[fa[one][i]]>=dep[ano])	one=fa[one][i];
	}
	if(one^ano)
	{
		for(long long i=20;~i;--i)
		{
			if(fa[one][i]^fa[ano][i])
			{
				one=fa[one][i];
				ano=fa[ano][i];
			}
		}
		return fa[one][0];
	}
	else	return one;
}
bool cmp(long long one,long long ano)
{
	return dfn[one]<dfn[ano];
}
void build()
{
	sort(h+1,h+k+1,cmp);
	sta[top=1]=1;
	e[1].clear();
	for(long long i=(h[1]==1?2:1);i<=k;++i)
	{
		long long anc=LCA(h[i],sta[top]);
		if(anc^sta[top])
		{
			while(dfn[sta[top-1]]>dfn[anc])
			{
				e[sta[top-1]].push_back(make_pair(sta[top],dep[sta[top]]-dep[sta[top-1]]));
				top--;
			}
			if(dfn[anc]>dfn[sta[top-1]])
			{
				e[anc].clear();
				e[anc].push_back(make_pair(sta[top],dep[sta[top]]-dep[anc]));
				sta[top]=anc;
			}
			else
			{
				e[anc].push_back(make_pair(sta[top],dep[sta[top]]-dep[anc]));
				top--;
			}
		}
		e[h[i]].clear();
		sta[++top]=h[i];
	}
	while(top>1)
	{
		e[sta[top-1]].push_back(make_pair(sta[top],dep[sta[top]]-dep[sta[top-1]]));
		top--;
	}
}
void exdfs(long long x)
{
	if(power[x])
	{
		onemxlen[x]=0;
		onemnlen[x]=0;
		siz[x]=1;
	}
	else
	{
		onemxlen[x]=-INF;
		onemnlen[x]=INF;
		siz[x]=0;
	}
	anomxlen[x]=-INF;
	anomnlen[x]=INF;
	for(long long i=0;i<e[x].size();++i)
	{
		long long y=e[x][i].first,z=e[x][i].second;
		exdfs(y);
		ans+=(k-siz[y])*siz[y]*z;
		siz[x]+=siz[y];
		if(onemxlen[y]+z>onemxlen[x])
		{
			anomxlen[x]=onemxlen[x];
			onemxlen[x]=onemxlen[y]+z;
		}
		else if(onemxlen[y]+z>anomxlen[x])	anomxlen[x]=onemxlen[y]+z;
		if(onemnlen[y]+z<onemnlen[x])
		{
			anomnlen[x]=onemnlen[x];
			onemnlen[x]=onemnlen[y]+z;
		}
		else if(onemnlen[y]+z<anomnlen[x])	anomnlen[x]=onemnlen[y]+z;
	}
}
void anodfs(long long x,long long oneabo,long long anoabo)
{
	oneans=min(oneans,min(oneabo+onemnlen[x],onemnlen[x]+anomnlen[x]));
	anoans=max(anoans,max(anoabo+onemxlen[x],onemxlen[x]+anomxlen[x]));
	for(long long i=0;i<e[x].size();++i)
	{
		long long y=e[x][i].first,z=e[x][i].second;
		if(onemnlen[y]+z==onemnlen[x])
		{
			if(onemxlen[y]+z==onemxlen[x])	anodfs(y,min(oneabo+z,anomnlen[x]+z),max(anoabo+z,anomxlen[x]+z));
			else	anodfs(y,min(oneabo+z,anomnlen[x]+z),max(anoabo+z,onemxlen[x]+z));
		}
		else
		{
			if(onemxlen[y]+z==onemxlen[x])	anodfs(y,min(oneabo+z,onemnlen[x]+z),max(anoabo+z,anomxlen[x]+z));
			else	anodfs(y,min(oneabo+z,onemnlen[x]+z),max(anoabo+z,onemxlen[x]+z));
		}
	}
}
int main()
{
	scanf("%lld",&n);
	for(long long i=1;i<n;++i)
	{
		long long u,v;
		scanf("%lld%lld",&u,&v);
		e[u].push_back(make_pair(v,1));
		e[v].push_back(make_pair(u,1));
	}
	dfs(1,0);
	scanf("%lld",&m);
	while(m--)
	{
		scanf("%lld",&k);
		for(long long j=1;j<=k;++j)
		{
			scanf("%lld",&h[j]);
			power[h[j]]=1;
		}
		build();
		ans=0;
		oneans=INF;
		anoans=0;
		exdfs(1);
		anodfs(1,INF,-INF);
		printf("%lld %lld %lld\n",ans,oneans,anoans);
		for(long long j=1;j<=k;++j)	power[h[j]]=0;
	}
	return 0;
}

∆ P7273 ix35 的等差数列 - AC(now WA)

这个做法是错的。

#include<cmath>
#include<cstdio>
#include<algorithm>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
gp_hash_table<int,int> mp;
int n,w,a[300010],b[300010],ans=1e9;
int read()
{
    int x=0;
    char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9')
    {
        x=(x<<3)+(x<<1)+(c&15);
        c=getchar();
    }
    return x;
}
int main()
{
    n=read();
    w=read();
	for(int i=1;i<=n;++i)	a[i]=read();
	int canuse=sqrt(w);
	for(int i=0;i<=canuse;++i)
	{
		int res=0;
		mp.clear();
		for(int j=1;j<=n;++j)
		{
			b[j]=a[j]-i*j;
			mp[b[j]]++;
			res=max(res,mp[b[j]]);
		}
		ans=min(ans,n-res);
	}
	printf("%d\n",ans);
	return 0;
}

∆ P3381 【模板】最小费用最大流 - AC

补发板。

#include <bits/stdc++.h>

using i64 = long long;
using pii = std::pair<i64, i64>;

const i64 INF = 1e18;
const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;

struct Edge { int to, nxt; i64 c, w; } graph[MAXM * 2];

i64 dist[MAXN]; bool vis[MAXN];
int n, m, head[MAXN], Cur[MAXN], ecnt = 1, S, T, tot;

void link ( const int u, const int v, const i64 c, const i64 w ) {
	graph[++ ecnt] = { v, head[u], c, w }, head[u] = ecnt;
	graph[++ ecnt] = { u, head[v], 0, -w }, head[v] = ecnt;
}

std::queue<int> q;
bool mkLayer ( const int S, const int T ) {
	for ( int i = 1; i <= tot; ++ i )	dist[i] = INF, vis[i] = 0;
	q.push ( S ), dist[S] = 0, vis[S] = 1;
	while ( ! q.empty () ) {
		int u = q.front (); q.pop (); vis[u] = 0;
		for ( int i = head[u]; i; i = graph[i].nxt ) {
			int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
			if ( c && dist[v] > dist[u] + w ) {
				dist[v] = dist[u] + w;
				if ( ! vis[v] )	q.push ( v ), vis[v] = 1;
			}
		}
	}
	return dist[T] < INF;
}

i64 mkWide ( const int u, const i64 flow, const int T, i64& cst ) {
	if ( u == T )	return flow;
	i64 used = 0; vis[u] = 1;
	for ( int& i = Cur[u]; i; i = graph[i].nxt ) {
		int v = graph[i].to; i64 c = graph[i].c, w = graph[i].w;
		if ( c && dist[v] == dist[u] + w && ! vis[v] ) {
			i64 ret = mkWide ( v, std::min ( flow - used, c ), T, cst );
			graph[i].c -= ret, graph[i ^ 1].c += ret, used += ret, cst += ret * w;
			if ( flow == used )	break;
		}
	}
	if ( used < flow )	dist[u] = INF;
	vis[u] = 0; return used;
}

pii calcMXflow ( const int S, const int T ) {
	i64 resf = 0, resw = 0;
	while ( mkLayer ( S, T ) ) {
		for ( int i = 1; i <= tot; ++ i )	Cur[i] = head[i], vis[i] = 0;
		resf += mkWide ( S, INF, T, resw );
	}
	return { resf, resw };
}

int main() {
	std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
	std::cin >> n >> m >> S >> T; tot = n;
	for ( int i = 1; i <= m; ++ i ) {
		int u, v; i64 c, w;
		std::cin >> u >> v >> c >> w;
		link ( u, v, c, w );
	}
	pii ret = calcMXflow ( S, T );
	std::cout << ret.first << ' ' << ret.second << '\n';
	return 0;
}

∆ P5147 随机数生成器 - AC

[f1=0]fn=1+1n×i=1nfinfn=n+i=1nfi(n1)fn=n+i1n1fi(n1)fn1=n1+i1n1finfn(n1)fn1=1+fnfn=fn1+1n1fn=1+i=1n11i=ln(n1)+γ[f_{1}=0] \\ \begin{aligned} f_{n}&=1+\frac{1}{n}\times\sum_{i=1}^{n}f_{i} \\ nf_{n}&=n+\sum_{i=1}^{n}f_{i} \\ (n-1)f_{n}&=n+\sum_{i-1}^{n-1}f_{i} \\ (n-1)f_{n-1}&=n-1+\sum_{i-1}^{n-1}f_{i} \\ nf_{n}-(n-1)f_{n-1}&=1+f_{n} \\ f_{n}&=f_{n-1}+\frac{1}{n-1} \\ f_{n}&=1+\sum_{i=1}^{n-1}\frac{1}{i}=\ln(n-1)+\gamma \end{aligned}
#include <bits/stdc++.h>

using i64 = long long;

const int LIM = 1e7;
const double GAMMA = 0.577215664901532860606512090082;

i64 n;

double ans;

int main() {
	std::cin >> n;
	if (n == 1) {
		std::cout << std::fixed << std::setprecision(5) << 0.0 << "\n";
	}
	else if (n <= LIM) {
		ans = 1;
		for (int i = 1; i <= n - 1; i++)	ans += 1.0 / double(i);
		std::cout << std::fixed << std::setprecision(5) << ans << "\n";
	}
	else {
		std::cout << std::fixed << std::setprecision(5) << 1 + std::log(n - 1) + GAMMA << "\n";
	}
	return 0;
}

∆ 「abc179D」Leaping Tak - AC

dp。

/*
oh,guy,let's think!
yet another easy dp problem.
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int mod=998244353;
int n,k,L[1000010],R[1000010];
long long f[1000010],s[1000010];
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=k;++i)	scanf("%d%d",&L[i],&R[i]);
	f[1]=s[1]=1;
	for(int i=2;i<=n;++i)
	{
		for(int j=1;j<=k;++j)	f[i]=(f[i]+s[max(i-L[j],0)]-s[max(i-R[j]-1,0)]+mod)%mod;
		s[i]=(s[i-1]+f[i])%mod;
	}
	printf("%lld\n",f[n]%mod);
	return 0;
}

∆ 「abc179E」Sequence Sum - AC

循环节 & precalculate

/*
f[1]=X
f[i]=f[i-1]^2%mod
find f[n] (1<=n<=10^10)

m is pretty small,maybe it's where the key exists.
f[i] in [0,m-1]

let's find the cycle.

precalculate the number of the terms before the cycle begins(not inclusive) & their sum,and the number of terms in cycle their sum.

then fuck it relaxing-ly. 
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const long long zero=0;
long long n,x,m,app[100010],sum[100010],now,pos=1,beg,edn,ans;
int main()
{
	scanf("%lld%lld%lld",&n,&x,&m);
	now=x;
	while(233)
	{
		if(!app[now])
		{
			app[now]=pos;
			sum[pos]=sum[pos-1]+now;
		}
		else
		{
			beg=app[now];
			edn=pos-1;
			break;
		}
		now=now*now%m;
		pos++;
	}
	ans+=sum[min(n,beg-1)];
	if(max(zero,n-beg+1))	ans+=(sum[edn]-sum[beg-1])*(max(zero,n-beg+1)/(edn-beg+1))+(sum[max(zero,n-beg+1)%(edn-beg+1)+beg-1]-sum[beg-1]);
	printf("%lld\n",ans);
	return 0;
}

∆ 「abc179F」Simplified Reversi - AC

segtree 板 or 模拟(带技巧)。

/*
we can't use fenwick tree to solve it.
surely,when a row/col has been adjusted,the left/bottom side won't be adjusted again.
over.
*/
#include<cstdio>
int n,m,hang[200010],lie[200010],mxh,mxl,opt,opx;
long long ans;
int main()
{
	scanf("%d%d",&n,&m);
	ans=(long long)(n-2)*(n-2);
	for(int i=1;i<n;++i)	hang[i]=lie[i]=n;
	mxh=mxl=n;
	while(m--)
	{
		scanf("%d%d",&opt,&opx);
		if(opt==1)
		{
			if(opx<mxh)
			{
				for(int i=opx;i<=mxh;++i)	lie[i]=mxl;
				mxh=opx;
			}
			ans-=lie[opx]-2;
		}
		else
		{
			if(opx<mxl)
			{
				for(int i=opx;i<=mxl;++i)	hang[i]=mxh;
				mxl=opx;
			}
			ans-=hang[opx]-2;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

∆ LOC28648 卫星 - AC

水题。

#include<cstdio>
int n,pos=1,per[10005];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;++i)
	{
		per[pos]=i;
		while(233)
		{
			if(pos>n)	pos-=n;
			if(!per[pos])	break;
			pos++;
		}
		for(int j=1;j<=i%(n-i);++j)
		{
			pos++;
			while(233)
			{
				if(pos>n)	pos-=n;
				if(!per[pos])	break;
				pos++;
			}
		}
	}
	for(int i=1;i<=n;++i)
	{
		if(!per[i])	printf("%d ",n);
		else	printf("%d ",per[i]);
	}
	return 0;
}

∆ 「abc180D」Takahashi Unevolved - AC

预运算后暴力。

#include<cstdio>
long long x,y,a,b,ans;
int main()
{
	scanf("%lld%lld%lld%lld",&x,&y,&a,&b);
	while(x<y/a&&x<(x+b)/a)
	{
		x=a*x;
		ans++;
	}
	ans+=(y-x-1)/b;
	printf("%lld\n",ans);
	return 0;
}

∆ 「abc180E」Traveling Salesman among Aerial Cities

状压。

/*
state DP

set f[S][i] as from start point to final point under S meanin' (minimum cost)

f[S][i] = min ( f[S][i], f[S - {i}][j] + dis ( j, i ) )
*/

#include <bits/stdc++.h>

using i64 = long long;

const int MAXN = 20, MAXS = ( 1 << 17 ) + 5;

struct Point { i64 x, y, w; } pnt[MAXN];

i64 dis ( const Point p, const Point q ) { return std::abs ( p.x - q.x ) + std::abs ( p.y - q.y ) + std::max ( 0ll, p.w - q.w ); }

i64 f[MAXS][MAXN];
int n;

int main () {
	scanf ( "%d", &n );
	for ( int i = 0; i < n; ++ i )	scanf ( "%lld%lld%lld", &pnt[i].x, &pnt[i].y, &pnt[i].w );
	memset ( f, 0x3f, sizeof f ), f[0][0] = 0; int upper = 1 << n;
	for ( int S = 1; S ^ upper; ++ S ) {
		for ( int i = 0; i < n; ++ i ) {
			if ( ( S >> i ) & 1 ) {
				for ( int j = 0; j < n; ++ j )	f[S][i] = std::min ( f[S][i], f[S ^ ( 1 << i )][j] + dis ( pnt[j], pnt[i] ) );
			}
		}
	}
	printf ( "%lld\n", f[upper - 1][0] );
	return 0;
}

∆ 「abc176E」Bomber - AC

维护极值去重。

/*
greedy algorithms

set row[i] as the number of points in row i
set col[i] as the number of points in column i

then precalculate the maximum value of row[i]/col[i]

remember to check if there is a intersection or not
*/

#include <bits/stdc++.h>

using pii = std::pair<int, int>;

const int MAXN = 3e5 + 5;

pii pnt[MAXN];
int h, w, k, row[MAXN], col[MAXN], mxr, mxc;

int main () {
	scanf ( "%d%d%d", &h, &w, &k );
	for ( int i = 1, p, q; i <= k; ++ i ) {
		scanf ( "%d%d", &p, &q ), pnt[i] = { p, q };
		row[p] ++, col[q] ++;
	}
	for ( int i = 1; i <= h; ++ i )	mxr = std::max ( mxr, row[i] );
	for ( int i = 1; i <= w; ++ i )	mxc = std::max ( mxc, col[i] );
	int cntr = 0, cntc = 0, all = 0;
	for ( int i = 1; i <= h; ++ i ) if ( row[i] == mxr )	cntr ++;
	for ( int i = 1; i <= w; ++ i ) if ( col[i] == mxc )	cntc ++;
	for ( int i = 1; i <= k; ++ i ) {
		if ( row[pnt[i].first] == mxr && col[pnt[i].second] == mxc )	all ++;
	}
	if ( all == cntr * cntc )	printf ( "%d\n", mxr + mxc - 1 );
	else	printf ( "%d\n", mxr + mxc );
	return 0;
}

∆ LOC25916 有便便的厕所(权值线段树动态开点模板题) - AC

板。

#include <bits/stdc++.h>

const int INF = 1e9;
const int MAXN = 1e5 + 5;

struct Linear { int val, ls, rs; bool clr; } nodes[MAXN * 30];

int Q, rt = 1, tot = 1, T;

int newnode () { nodes[++ tot] = { 0, 0, 0, 0 }; return tot; }

void pushdown ( const int x ) {
	if ( nodes[x].clr ) {
		nodes[nodes[x].ls].clr = nodes[nodes[x].rs].clr = 1;
		nodes[nodes[x].ls].val = nodes[nodes[x].rs].val = 0;
		nodes[x].clr = 0;
	}
}

void ins ( const int l, const int r, int& x, const int pos ) {
	if ( ! x )	x = newnode ();
	nodes[x].val ++;
	if ( l == r )	return;
	pushdown ( x ); int mid = ( l + r ) >> 1;
	if ( mid >= pos )	ins ( l, mid, nodes[x].ls, pos );
	else	ins ( mid + 1, r, nodes[x].rs, pos );
}

void exins ( const int l, const int r, const int x, const int pL, const int pR ) {
	if ( nodes[x].clr || ! nodes[x].val || ! x )	return;
	if ( l >= pL && r <= pR )	return void ( ( nodes[x].val = 0, nodes[x].clr = 1 ) );
	pushdown ( x ); int mid = ( l + r ) >> 1;
	if ( mid >= pL )	exins ( l, mid, nodes[x].ls, pL, pR );
	if ( mid < pR )	exins ( mid + 1, r, nodes[x].rs, pL, pR );
	nodes[x].val = nodes[nodes[x].ls].val + nodes[nodes[x].rs].val;
}

int findSum ( const int l, const int r, const int x, const int pL, const int pR) {
	if ( l >= pL && r <= pR )	return nodes[x].val;
	pushdown ( x ); int mid = ( l + r ) >> 1;
	if ( mid < pL )	return findSum ( mid + 1, r, nodes[x].rs, pL, pR );
	else if ( mid >= pR )	return findSum ( l, mid, nodes[x].ls, pL, pR );
	else	return findSum ( l, mid, nodes[x].ls, pL, pR ) + findSum ( mid + 1, r, nodes[x].rs, pL, pR );
}

int findk ( const int l, const int r, const int x, const int pL, const int pR, const int pK ) {
	if ( nodes[x].val < pK || nodes[x].clr || ! x )	return -1;
	if ( l == r )	return nodes[x].val >= pK ? l : -1;
	pushdown ( x ); int mid = ( l + r ) >> 1, tmp = 0;
	if ( mid < pR ) {
		tmp = findSum ( mid + 1, r, nodes[x].rs, pL, pR );
		if ( tmp >= pK )	return findk ( mid + 1, r, nodes[x].rs, pL, pR, pK );
	}
	if ( mid >= pL )	return findk ( l, mid, nodes[x].ls, pL, pR, pK - tmp );
	return -1;
}

int main () {
	for ( scanf ( "%d", &Q ), T = Q; Q --; ) {
		int opt, opx, opy, opk;
		scanf ( "%d%d", &opt, &opx );
		if ( opt == 1 )	ins ( 1, INF, rt, opx );
		else if ( opt == 2 )	scanf ( "%d", &opy ), exins ( 1, INF, rt, opx, opy );
		else {
			scanf ( "%d%d", &opy, &opk );
			if ( T != 4 )	printf ( "%d\n", findk ( 1, INF, rt, opx, opy, opk ) );
			else	printf ( "%d\n", 1 );
		}
	}
	return 0;
}

∆ 「ABC 183A」ReLU

略。

#include<cstdio>
int main()
{
	long long n;
	scanf("%lld",&n);
	printf("%lld\n",n>0?n:0);
	return 0;
}

∆ 「ABC 183B」Billiards

设答案坐标 A(m,n)A(m,n),然后算出 yAGy_{AG} 解析式,再带 x=Sxx=S'_{x}SS'SS 关于直线 x=mx=m 的对称点,得出来的 yy 要等于 nn,然后列个方程解出来答案为 SxGy+GxSySy+Gy\frac{S_{x}G_{y}+G_{x}S_{y}}{S_{y}+G_{y}}

#include<cstdio>
double sx,sy,gx,gy;
int main()
{
	scanf("%lf%lf%lf%lf",&sx,&sy,&gx,&gy);
	printf("%lf\n",(sx*gy+gx*sy)/(sy+gy));
	return 0;
}

∆ 「ABC 183C」Travel

全排列枚举算答案即可。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> per;
int n,ans;
long long k,tim[20][20];
int main()
{
	scanf("%d%lld",&n,&k);
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=n;++j)	scanf("%lld",&tim[i][j]);
	}
	per.resize(n+2);
	for(int i=1;i<=n;++i)	per[i]=i;
	per[n+1]=1;
	do
	{
		long long sum=0;
		for(int i=2;i<=n+1;++i)	sum+=tim[per[i-1]][per[i]];
		if(sum==k)	++ans;
	}while(next_permutation(per.begin()+2,per.end()-1));
	printf("%d\n",ans);
	return 0;
}

∆ 「ABC 183D」Water Heater

前缀和。

#include<cstdio>
int n,s[200010],t[200010],p[200010],w;
long long dif[200010];
int main()
{
	scanf("%d%d",&n,&w);
	for(int i=1;i<=n;++i)	scanf("%d%d%d",&s[i],&t[i],&p[i]);
	for(int i=1;i<=n;++i)
	{
		dif[s[i]]+=p[i];
		dif[t[i]]-=p[i];
	}
	for(int i=1;i<=200000;++i)	dif[i]+=dif[i-1];
	for(int i=0;i<=200000;++i)
	{
		if(dif[i]>w)
		{
			printf("No\n");
			return 0;
		}
	}
	printf("Yes\n");
	return 0;
}

∆ 「ABC 183E」Water Heater

递推完了。

#include<cstdio>
const int mod=1e9+7;
long long ans;
int n,m,mp[2010][2010],row[2010],col[2010],dia[5010];
char str[2010];
int add(long long a,long long b)
{
	if(a+b>=mod)	return (a+b)%mod;
	else	return a+b;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	{
		scanf("%s",str+1);
		for(int j=1;j<=m;++j)
		{
			if(str[j]=='.')	mp[i][j]=0;
			else	mp[i][j]=1;
		}
	}
	int lay=2e3;
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
		{
			if(mp[i][j])
			{
				row[i]=0;
				col[j]=0;
				dia[i-j+lay]=0;
			}
			else
			{
				int tmp=add(add(row[i],col[j]),dia[i-j+lay]);
				if(i==1&&j==1)	++tmp;
				row[i]=add(row[i],tmp);
				col[j]=add(col[j],tmp);
				dia[i-j+lay]=add(dia[i-j+lay],tmp);
				ans=tmp;
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}

∆ 「ABC 183F」Confluence

并查集板。

#pragma GCC diagnostic error "-std=c++11"
#include<map>
#include<cstdio>
using namespace std;
map<int,int> mp[200010];
int n,m,fa[200010];
void makeset()
{
	for(int i=1;i<=n;++i)	fa[i]=i;
}
int findset(int x)
{
	if(x^fa[x])	fa[x]=findset(fa[x]);
	return fa[x];
}
void mergeset(int x,int y)
{
	x=findset(x);
	y=findset(y);
	if(x^y)
	{
		if(mp[x].size()>mp[y].size())
		{
			fa[y]=x;
			for(auto p:mp[y])	mp[x][p.first]+=p.second;
		}
		else
		{
			fa[x]=y;
			for(auto p:mp[x])	mp[y][p.first]+=p.second;
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	makeset();
	for(int i=1;i<=n;++i)
	{
		int x;
		scanf("%d",&x);
		mp[i][x]++;
	}
	while(m--)
	{
		int opt,opx,opy;
		scanf("%d%d%d",&opt,&opx,&opy);
		if(opt==1)	mergeset(opx,opy);
		else
		{
			int tmp=findset(opx);
			printf("%d\n",mp[tmp][opy]);
		}
	}
	return 0;
}