模板

\[ft61 \]

试机

  • 编译选项

  • extc++

  • cerr

  • 测速


配置

  • vscode
"editor.rulers": [85],
  • vim
set nu
set mouse=a
  • 缺省源
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std; using namespace __gnu_pbds; using namespace __gnu_cxx;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define rFor(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define pb emplace_back
#define sz(a) int((a).size())
#define all(a) (a).begin(),(a).end()
#define fi first
#define se second
#define mkp make_pair
#define mem(a,x,n) memset(a,x,sizeof(*a)*((n)+2))
typedef long long LL; typedef vector<int> Vi; typedef pair<int,int> Pii;
auto ckmax=[](auto &x,auto y) { return x<y ? x=y,true : false; };
auto ckmin=[](auto &x,auto y) { return y<x ? x=y,true : false; };
template<typename T=int>T read() { T x; cin>>x; return x; }
sfmt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int l,int r) { return uniform_int_distribution<>(l,r)(mt); }



void MAIN() {

} signed main() {
#ifdef FS
	freopen("in","r",stdin); freopen("out","w",stdout);
#endif
	ios::sync_with_stdio(0);cin.tie(0);
	int lft=1; while( lft-- ) {
		MAIN();
	}
	return 0;
}

C++

__gnu_pbds

  • tree
int ind;
tree<Pii,null_type,less<>,rb_tree_tag,tree_order_statistics_node_update> rbt;

rbt.insert({x,++ind});
rbt.erase(rbt.lower_bound({x,0}));
rbt.order_of_key({x,0}); // < x 的数的个数
rbt.find_by_order(x-1)->fi; // 第 x 小
(--rbt.lower_bound({x,0}))->fi; // < x 的最大数
rbt.lower_bound({x+1,0})->fi; // > x 的最小数

DP

斜率优化

\(\max_{i}\{kx_{i}+y_{i}\}\)\(x_{i},y_{i},k\)int

\((x_{i},y_{i})\) 建上凸包,查询斜率为 \(-k\) 的直线的最大截距

  • 静态建
struct Vec {
	LL x,y; Vec(LL x=0,LL y=0):x(x),y(y){}
	bool operator < (const Vec &rhs) { return x!=rhs.x ? x<rhs.x : y<rhs.y; }
	Vec operator - (const Vec &rhs) { return {x-rhs.x, y-rhs.y}; }
	LL operator & (const Vec &rhs) { return x*rhs.y-y*rhs.x; } // 叉乘
};

Vec s[N]; int t = 0;
sort(all(p));
for(auto i : p) {
	while( t > 1 && (s[t]-s[t-1]&i-s[t-1]) >= 0 ) --t;
	s[++t] = i;
}
  • 双指针查询
sort(all(q),[](int x,int y){return k[x]<k[y];});
int j = 1;
for(int i : q) {
	auto f=[&](int j) { return k[j]*s[i].x+s[i].y; };
	while( j < t && f(j+1) > f(j) ) ++j;
	ans[i] = f(j);
}
  • 二分查询

DDP

  • LG4751 【模板】"动态DP"&动态树分治(加强版)

单点修改,最大权独立集

const int N = 1e6+5, inf = 0x3f3f3f3f;
int n,m,ans,a[N];
VI e[N];

struct Mat {
	int a[2][2];
	Mat() { memset(a,0xcf,sizeof a); }
	int* operator [] (int i) { return a[i]; }
	const int* operator [] (int i) const { return a[i]; }
	Mat operator * (const Mat &b) const {
		Mat res;
		res[0][0] = max(a[0][0]+b[0][0],a[0][1]+b[1][0]),
		res[0][1] = max(a[0][0]+b[0][1],a[0][1]+b[1][1]),
		res[1][0] = max(a[1][0]+b[0][0],a[1][1]+b[1][0]),
		res[1][1] = max(a[1][0]+b[0][1],a[1][1]+b[1][1]);
		return res;
	}
};

#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
#define fa(u) t[u].fa
struct LCT {
	struct Node { int fa,ch[2],g[2]; Mat f; } t[N];
	bool nrt(int u) { return ls(fa(u))==u || rs(fa(u))==u; }
	bool wh(int u) { return rs(fa(u))==u; }
	void up(int u) {
		t[u].f[0][0] = t[u].f[1][0] = t[u].g[0],
		t[u].f[0][1] = t[u].g[1], t[u].f[1][1] = -inf;
		if( ls(u) ) t[u].f = t[u].f * t[ls(u)].f;
		if( rs(u) ) t[u].f = t[rs(u)].f * t[u].f;
	}
	void rotate(int x) {
		int y = fa(x), z = fa(y), k = wh(x), w = t[x].ch[!k];
		if( nrt(y) ) t[z].ch[wh(y)] = x; t[x].ch[!k] = y, t[y].ch[k] = w;
		fa(w) = y, fa(y) = x, fa(x) = z, up(y);
	}
	void splay(int u) {
		for(int fa; fa = fa(u), nrt(u); rotate(u))
			if( nrt(fa) ) rotate(wh(fa)==wh(u)?fa:u);
		up(u);
	}
	void add(int u,int v) {
		t[u].g[0] += max(t[v].f[0][0],t[v].f[0][1]),
		t[u].g[1] += t[v].f[0][0];
	}
	void del(int u,int v) {
		t[u].g[0] -= max(t[v].f[0][0],t[v].f[0][1]),
		t[u].g[1] -= t[v].f[0][0];
	}
	void access(int x) {
		for(int u = x, v = 0; u; u = fa(v=u)) {
			splay(u);
			if( rs(u) ) add(u,rs(u));
			if( (rs(u) = v) ) del(u,v);
			up(u);
		}
		splay(x);
	}
	void debug() {
		For(i,1,n)
			cerr<<fa(i)<<" "<<ls(i)<<" "<<rs(i)<<"  "
				<<t[i].g[0]<<" "<<t[i].g[1]<<endl;
		cerr<<endl;
	}
} lct;
#undef fa

void dfs(int u,int fa) {
	for(int v : e[u]) if( v != fa )
		dfs(v,u), lct.t[v].fa = u, lct.add(u,v);
	lct.t[u].g[1] += a[u], lct.up(u);
}

signed main() {
	io>>n>>m; For(i,1,n) io>>a[i];
	Rep(i,1,n, x,y) io>>x>>y, e[x].pb(y), e[y].pb(x);
	dfs(1,0);
	while( m-- ) {
		int u,x; io>>u>>x; u ^= ans;
		lct.access(u), lct.t[u].g[1] += x-a[u], lct.up(u), a[u] = x;
		lct.splay(1);
		io<<(ans=max(lct.t[1].f[0][0],lct.t[1].f[0][1]))<<endl;
//		lct.debug();
	}
	return 0;
}

插头 DP

LG5056 【模板】插头 DP

四连通网格图,哈密顿回路计数

char readc() { char c; while((c=getchar())!='*'&&c!='.'); return c; }

const int N = 1e6+3;
int n,m,endx,endy,tot[2],st[2][N];
LL ans,f[2][N];
bool cur,a[15][15];

struct HT {
	int head[N],nxt[N];
	void clear() { tot[cur] = 0, memset(head,0,sizeof head); }
	void insert(int x,LL val) {
		int y = x % N;
		for(int i = head[y]; i; i = nxt[i])
			if( st[cur][i] == x ) return f[cur][i] += val, void();
		nxt[++tot[cur]] = head[y], head[y] = tot[cur];
		st[cur][tot[cur]] = x, f[cur][tot[cur]] = val;
	}
} h;

#define get(s,i) ((s>>(i)*2)&3)
#define set(x,i) (x<<(i)*2)

signed main() {
	read(n,m);
	For(i,1,n) For(j,1,m) if( readc() == '.' ) a[i][j] = 1, endx = i, endy = j;
	f[cur][tot[cur]=1] = 1;
	For(i,1,n) {
		For(j,1,tot[cur]) st[cur][j] <<= 2;
		For(j,1,m) {
			cur ^= 1, h.clear();
			For(k,1,tot[!cur]) {
				int s = st[!cur][k], r = get(s,j-1), d = get(s,j);
				LL dp = f[!cur][k];
				if( !a[i][j] ) {
					if( !r && !d ) h.insert(s,dp);
				} else if( !r && !d ) {
					if( a[i][j+1] && a[i+1][j] )
						h.insert(s+set(1,j-1)+set(2,j),dp);
				} else if( r && !d ) {
					if( a[i][j+1] ) h.insert(s-set(r,j-1)+set(r,j),dp);
					if( a[i+1][j] ) h.insert(s,dp);
				} else if( !r && d ) {
					if( a[i+1][j] ) h.insert(s-set(d,j)+set(d,j-1),dp);
					if( a[i][j+1] ) h.insert(s,dp);
				} else if( r == 1 && d == 1 ) {
					For(p,j+1,m, cnt = 1) {
						if( get(s,p) == 1 ) ++cnt;
						else if( get(s,p) == 2 && !--cnt ) {
							h.insert(s-set(1,j-1)-set(1,j)-set(1,p),dp);
							break;
						}
					}
				} else if( r == 2 && d == 2 ) {
					rFor(p,j-2,0, cnt = 1) {
						if( get(s,p) == 2 ) ++cnt;
						else if( get(s,p) == 1 && !--cnt ) {
							h.insert(s-set(2,j-1)-set(2,j)+set(1,p),dp);
							break;
						}
					}
				} else if( r == 2 && d == 1 ) h.insert(s-set(2,j-1)-set(1,j),dp);
				else if( i == endx && j == endy ) ans += dp;
			}
		}
	}
	write(ans);
	return ocl();
}

其他

  • 模拟退火
// NOIP2021 方差
const int N = 1e4+5;
int n,m,a[N];
bool wh[N];
LL ans=LLONG_MAX;
Vi b;

auto sq = [](auto x) { return x * x; };
LL cal() {
	static int tmp[N];
	LL ave = 0, res = 0;
	For(i,2,n) tmp[i] = tmp[i-1] + b[i-2];
	For(i,1,n) ave += tmp[i]; ave /= n;
	For(i,1,n) res += sq(tmp[i]-ave);
	return res / n;
}

void MAIN() {
	cin>>n; For(i,1,n) cin>>a[i], a[i] *= n;
	Rep(i,1,n) a[i] = a[i+1]-a[i]; sort(a+1,a+n);
	m = count(a+1,a+n,a[1]);
	while( (double)clock()/CLOCKS_PER_SEC < 0.98 ) {
		b.clear();
		Rep(i,1,n) wh[i] = rnd(0,1);
		rFor(i,n-1,1) if( wh[i] ) b.pb(a[i]);
		Rep(i,1,n) if( !wh[i] ) b.pb(a[i]);
		LL now = cal(); ckmin(ans,now);
		for(double T = 1e6; T > 1e-3; T *= 0.97) {
			int l = 0; while( b[l] != a[1] ) ++l;
			int p = rnd(0,n-1-m-1);
			auto c = b;
			if( p < l )
				b.erase(b.begin()+p),
				b.emplace(lower_bound(b.begin()+l+m-1,b.end(),c[p]),c[p]);
			else
				p += m,
				b.erase(b.begin()+p),
				b.emplace(lower_bound(b.begin(),b.begin()+l,c[p],greater<>()),c[p]);
			// Rep(i,0,n-1) if( b[i] == a[1] ) {
			// 	Rep(j,0,i) assert(b[j]>=b[j+1]);
			// 	Rep(j,i+1,n-1) assert(b[j-1]<=b[j]);
			// 	break;
			// }
			LL res = cal();
			if( res < now || exp((now-res)/T)*UINT_MAX > mt() ) ckmin(ans, now=res);
			else swap(b,c);
		}
	}
	cout<<ans;
}
  • assert
// 第一行
#ifndef FS
	#define NDEBUG
#endif
  • 高精度类

不压位,\(O(n^2)\) 乘法

struct bint : Vi {
	bint() { resize(1); }
	bint(int x) { clear(); for(; x; x/=10) emplace_back(x%10); }
	void clr() { while( size() > 1 && !back() ) pop_back(); }
	friend istream& operator >> (istream &io,bint &a) {
		string s; io>>s, reverse(all(s));
		if( s.back() == '-' ) s.pop_back();
		a.resize(sz(s)); Rep(i,0,sz(s)) a[i] = s[i]-'0';
		return io;
	}
	friend ostream& operator << (ostream &io,const bint &a)
        { rFor(i,sz(a)-1,0) cout<<a[i]; return io; }
	friend bool operator < (const bint &a,const bint &b) {
		if( sz(a) != sz(b) ) return sz(a) < sz(b);
		rFor(i,sz(a)-1,0) if( a[i] != b[i] ) return a[i] < b[i];
		return 0;
	}
	friend bint operator + (const bint &a,const bint &b) {
		bint c = a; c.resize(max(sz(a),sz(b))+1);
		Rep(i,0,sz(b)) c[i] += b[i];
		Rep(i,0,sz(c)) if( c[i] >= 10 ) ++c[i+1], c[i] -= 10;
		return c.clr(), c;
	}
	friend bint operator * (const bint &a,const bint &b) {
		bint c; c.resize(sz(a)+sz(b)+1);
		Rep(i,0,sz(a)) Rep(j,0,sz(b)) c[i+j] += a[i] * b[j];
		Rep(i,0,sz(c)) if( c[i] >= 10 ) c[i+1] += c[i]/10, c[i] %= 10;
		return c.clr(), c;
	}
	friend bint operator - (bint a,bint b) {
		b.resize(sz(a));
		Rep(i,0,sz(a)) {
			if( a[i] < b[i] ) --a[i+1], a[i] += 10;
			a[i] -= b[i];
		}
		return a.clr(), a;
	}
};

压位,乘法

  • 分数类

  • 取模类

mint(int x) 要求 x < 2*mod

const int mod = 998244353;
struct mint {
	int x; mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
	mint(LL y) { y%=mod, x=y<0?y+mod:y; }
	mint& operator += (const mint &b) { x=x+b.x<mod?x+b.x:x+b.x-mod; return *this; }
	mint& operator -= (const mint &b) { x=x<b.x?x-b.x+mod:x-b.x; return *this; }
	mint& operator *= (const mint &b) { x=1ll*x*b.x%mod; return *this; }
	friend mint operator + (mint a,const mint &b) { return a+=b; }
	friend mint operator - (mint a,const mint &b) { return a-=b; }
	friend mint operator * (mint a,const mint &b) { return a*=b; }
};	mint Pow(mint a,LL b=mod-2) { mint c(1);for(;b;b>>=1,a*=a)if(b&1)c*=a;return a; }
  • Barrett reduction

【条件】

struct {
	LL p,m;
	void init(int mod) { p = mod, m = (1ull<<63)/p; }
	LL operator () (LL x) {
		LL res = x-(__int128(x)*m>>63)*p;
		return res<p ? res : res-p;
	}
} mod;
  • 快读快写
#define getchar() getchar_unlocked()
struct IO {
	IO& operator >> (char &x) { while(isspace(x=getchar())); return *this; }
	IO& operator >> (char *s) {
		while(isspace(*s=getchar())); while(isgraph(*++s=getchar()));
		return *s=0, *this;
	}
	template<typename T>IO& operator >> (T &x) {
		x=0;bool f=0;char c;while(!isdigit(c=getchar()))f|=c=='-';
		do x=x*10+c-48;while(isdigit(c=getchar()));if(f)x=-x;
		return *this;
	}
} io;
  • linux 对拍

shell

clear; g++ g.cpp -og -DFS -O2
let i=0; while true; do
	let i++; printf "#$i\n"
	./g; ./a; ./a0
	if ! diff out ans -bB; then break; fi
done
  • windows 对拍

cpp

for(int i = 1; ; ++i) {
	system("ag.exe"), system("a0.exe");
	double s = clock(); system("a.exe"); double t = clock();
	if( system("fc a.ans a.out") ) puts("WA"), exit(0);
	printf("#%d: %.0lfms\n",i,t-s);
}
  • 交互

所有输入都要读

endl 换行

posted @ 2023-10-09 19:53  ft61  阅读(91)  评论(1)    收藏  举报