各类模板(不定期更新)

次小生成树

LOJ10133 洛谷4180 BZOJ 1977

#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=1e5+5,maxm=6e5+5;
struct edge {int x,y,w;} e[maxm];
inline bool operator <(edge a,edge b) {return a.w<b.w;}
long long ans,bas;
int son[maxm],w[maxm],nxt[maxm],lnk[maxn],vis[maxm];
int N,M,tot,fa[maxn],dep[maxn],F[maxn][18],V[maxn][18][2];
inline int read() {
	int ret=0,f=1,ch=getchar();
	for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
	for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
	return ret*f;
}
inline int getfa(int x) {return fa[x]==x?x:fa[x]=getfa(fa[x]);}
inline void add_edge(int x,int y,int z) {
	son[++tot]=y,nxt[tot]=lnk[x],lnk[x]=tot,w[tot]=z;
	son[++tot]=x,nxt[tot]=lnk[y],lnk[y]=tot,w[tot]=z;
}
void dfs(int x,int pre) {
	for (int k=lnk[x],v; k; k=nxt[k]) if ((v=son[k])^pre)
		dep[v]=dep[x]+1,F[v][0]=x,V[v][0][0]=w[k],dfs(v,x);
}
void Init() {
	for (int j=1; j<18; ++j)
		for (int i=1,fa; i<=N; ++i) {
			F[i][j]=F[fa=F[i][j-1]][j-1];
			V[i][j][0]=max(V[i][j-1][0],V[fa][j-1][0]);
			V[i][j][1]=max(V[i][j-1][1],V[fa][j-1][1]);
			if (V[i][j-1][0]^V[fa][j-1][0])
				V[i][j][1]=max(V[i][j][1],min(V[i][j-1][0],V[fa][j-1][0]));
		}
}
inline int Get_Max(int &ret,int x,int i,int val) {
	if (val>V[x][i][0]) ret=max(ret,V[x][i][0]);
	else ret=max(ret,V[x][i][1]);
}
inline int Query(int x,int y,int val) {
	if (dep[x]<dep[y]) swap(x,y);
	int ret=0,d=dep[x]-dep[y];
	for (int i=0; i<18; ++i) if ((1<<i)&d) Get_Max(ret,x,i,val),x=F[x][i];
	if (x==y) return ret;
	for (int i=17; i>=0; --i) if (F[x][i]^F[y][i])
		Get_Max(ret,x,i,val),Get_Max(ret,y,i,val),x=F[x][i],y=F[y][i];
	return Get_Max(ret,x,0,val),Get_Max(ret,y,0,val),ret;
}
int main() {
	N=read(),M=read();
	for (int i=1; i<=N; ++i) fa[i]=i;
	for (int i=1; i<=M; ++i) e[i]=(edge){read(),read(),read()};
	sort(e+1,e+1+M);
	for (int i=1,fx,fy; i<=M; ++i) if ((fx=getfa(e[i].x))^(fy=getfa(e[i].y)))
		fa[fx]=fy,bas+=e[i].w,add_edge(e[i].x,e[i].y,e[i].w),vis[i]=1;
	dfs(1,0),Init(),ans=1ll<<60;
	for (int i=1; i<=M; ++i) if (!vis[i])
		ans=min(ans,bas-Query(e[i].x,e[i].y,e[i].w)+e[i].w);
	return printf("%lld\n",ans),0;
}

SPFA(压行)

void spfa() {
	std :: deque <int> Q;
	register int u,v,k;
	memset(vis,0,sizeof vis);
	memset(dis,0x3f,sizeof dis),Q.push_back(S),dis[S]=0;
	while (!Q.empty())
		for (vis[u=Q.front()]=0,k=lnk[u],Q.pop_front(); k; k=nxt[k])
			if (dis[v=son[k]]>dis[u]+w[k]) {
				dis[v]=dis[u]+w[k];
				if (!vis[v])
					if (vis[v]=1,!Q.empty()&&dis[Q.front()]>dis[v]) Q.push_front(v);
					else Q.push_back(v);
			}
}

树状数组(区间加,区间和)

推导过程

#include<cstdio>
#include<string>
inline int read() {
	int ret=0,f=1;char ch=getchar();
	for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
	for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
	return ret*f;
}
typedef long long LL;
const int maxn=1e6+5;
int N,Q;LL c1[maxn],c2[maxn];
inline void Add(LL x,LL dat) {
	for (int i=x; i<=N; i+=i&-i) c1[i]+=dat,c2[i]+=x*dat;
}
inline LL Query(LL x) {
	LL ret=0;
	for (int i=x; i; i-=i&-i) ret+=(x+1)*c1[i]-c2[i];
	return ret;
}
int main() {
	register int i,x,o,L,R;
	for (N=read(),Q=read(),i=1; i<=N; ++i) x=read(),Add(i,x),Add(i+1,-x);
	for (; Q--; ) if ((o=read())==1)
			L=read(),R=read(),x=read(),Add(L,x),Add(R+1,-x);
	else	L=read(),R=read(),printf("%lld\n",Query(R)-Query(L-1));
	return 0;
}

双哈希

typedef unsigned long long ull;
typedef pair<ull, ull> puu;
const int maxn = 1e5 + 5;
const ull MOD1 = 998244353;
const ull MOD2 = 1e9 + 7;
char s[maxn];
ull hsh1[maxn], hsh2[maxn], bas1[maxn], bas2[maxn];
ull rh1[maxn], rh2[maxn];
inline puu hash_p(int L, int R) { // 正方向的哈希
    return make_pair(
        (hsh1[R] + MOD1 - hsh1[L - 1] * bas1[R - L + 1] % MOD1) % MOD1,
        (hsh2[R] + MOD2 - hsh2[L - 1] * bas2[R - L + 1] % MOD2) % MOD2
    );
}
inline puu hash_n(int L, int R) { // 负方向的哈希
    return make_pair(
        (rh1[L] + MOD1 - rh1[R + 1] * bas1[R - L + 1] % MOD1) % MOD1,
        (rh2[L] + MOD2 - rh2[R + 1] * bas2[R - L + 1] % MOD2) % MOD2
    );
}
bool equ(int l1, int r1, int l2, int r2) { // [l1, r1]与[l2, r2]相同
    return hash_p(l1, r1) == hash_p(l2, r2);
}
bool rev(int L, int R) { // [L, R]回文
    if (L >= R) return 1;
    return hash_p(L, R) == hash_n(L, R);
}
void hashinit(int len) { // 哈希初始化,len为字符串长度
    hsh1[0] = hsh2[0] = 0;
    bas1[0] = bas2[0] = 1;
    for (int i = 1; i <= len; ++i) {
        bas1[i] = (bas1[i - 1] * 233) % MOD1;
        bas2[i] = (bas2[i - 1] * 233) % MOD2;
        hsh1[i] = (hsh1[i - 1] * 233 % MOD1 + s[i] - 'a') % MOD1;
        hsh2[i] = (hsh2[i - 1] * 233 % MOD2+ s[i] - 'a') % MOD2;
    }
    rh1[len + 1] = rh2[len + 1] = 0;
    for (int i = len; i > 0; --i) {
        rh1[i] = (rh1[i + 1] * 233 % MOD1 + s[i] - 'a') % MOD1;
        rh2[i] = (rh2[i + 1] * 233 % MOD2 + s[i] - 'a') % MOD2;
    }
}

树哈希

打杭州站的不知道怎么判断树同构。知道G的结论却没有板子实在是太痛苦了qwq。

补了一下树哈希的板子

uoj树哈希板子题
杭州站痛苦回忆

// uoj的板子,求一颗树上有多少种不同构的子树
#include <bits/stdc++.h>
using namespace std;
inline int read() {
	int ret = 0, f = 1; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -f;
	for (; isdigit(ch); ch = getchar()) ret = ret * 10 + ch - 48;
	return ret * f;
}
typedef unsigned long long ull;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
ull base = rnd();
const int maxn = 1e6 + 5;
int N, lnk[maxn], tot, sz[maxn];
ull h[maxn];
struct edge { int v, nxt; } e[2 * maxn];
void add_edge(int u, int v) {
	e[++tot] = { v, lnk[u] }, lnk[u] = tot;
	e[++tot] = { u, lnk[v] }, lnk[v] = tot;
}
ull H(ull x) {
	return x * x * x * 11451419 + 19260817;
}
ull F(ull x) {
	return
		H(x & ((1ll << 32) - 1)) +
		H(x >> 32);
} // 我看不懂,但我大受震撼
void dfs(int u, int fa) {
	h[u] = base;
    for (int k = lnk[u]; k; k = e[k].nxt) {
        int & v = e[k].v;
        if (v == fa) continue;
		dfs(v, u);
		h[u] += F(h[v]);
    }
}
signed main() {
	N = read();
	for (int i = 1; i < N; ++i) {
		int u = read(), v = read();
		add_edge(u, v);
	}
	dfs(1, 0);
	sort(h + 1, h + 1 + N);
	printf("%d\n", unique(h + 1, h + 1 + N) - h - 1);
	return 0;
}

生成随机数

How to succinctly, portably, and thoroughly seed the mt19937 PRNG?有感
抄其中一方案记录

#include <cstdint> //`uint32_t`
#include <functional> //`std::hash`
#include <random> //`std::mt19937`
#include <iostream> //`std::cout`

static std::mt19937 rng;

static void seed(uint32_t seed) {
    rng.seed(static_cast<std::mt19937::result_type>(seed));
}
static void seed() {
    uint32_t t = static_cast<uint32_t>( time(nullptr) );
    std::hash<uint32_t> hasher; size_t hashed=hasher(t);
    seed( static_cast<uint32_t>(hashed) );
}

int main(int /*argc*/, char* /*argv*/[]) {
    seed();
    std::uniform_int_distribution<> dis(0, 5);
    std::cout << dis(rng);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值