次小生成树
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的板子,求一颗树上有多少种不同构的子树
#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);
}