Csp-s 考前模板复习
来自菜鸡 genshy 的·模板。
不保证没坑
冰茶机
for(int i = 1; i <= n; i++) fa[i] = i;
int find(int x)
{
if(fa[x] == x) return x;
else return fa[x] = find(fa[x]);
}
Dij
void Dij()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
priority_queue<pair<int,int> > q;
q.push(make_pair(0,1)); dis[1] = 0;
while(!q.empty())
{
int t = q.top().second; q.pop();
if(vis[t]) continue;
vis[t] = 1;
for(int i = head[t]; i; i = e[i].net)
{
int to = e[i].to;
if(dis[to] > dis[t] + e[i].w)
{
dis[to] = dis[t] + e[i].w;
q.push(make_pair(-dis[to],to));
}
}
}
}
最小生成树
void msc()
{
bool comp(node a,node b){ return a.w < b.w; }
sort(e+1,e+m+1,comp);
for(int i = 1; i <= m; i++)
{
int fx = find(e[i].u);
int fy = find(e[i].v);
if(fx == fy) continue;
fa[fx] = fy;
ans += e[i].w;
if(--num == 1) break;
}
}
01背包
void beibao()
{
for(int i = 1; i <= n; i++)
{
for(int j = m; j >= 0; j--)
{
if(j >= v[i]) f[j] = max(f[j],f[j-v[i]] + w[i]);
}
}
}
完全背包
void beibao_two()
{
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= m; j++)
{
if(j >= v[i]) f[j] = max(f[j],f[j-v[i]] + w[i]);
}
}
}
分组背包
void beibao_three()
{
for(int i = 1; i <= cnt; i++)
{
for(int j = m; j >= 0; j--)
{
for(int k = 1; k <= num[i]; k++)
{
if(j >= v[i][k]) f[j] = max(f[j],f[j-v[i][k]] + w[i][k]);
}
}
}
}
快速幂
int ksm(int a,int b)
{
int res = 1;
for(; b; b >>= 1)
{
if(b & 1) res = res * a % p;
a = a * a % p;
}
return res;
}
哈希
int Hsah(char *s,int len)
{
const int base = 128;
const int p = 998244353;
int tmp = 1;
for(int i = 1; i <= len; i++)
{
tmp = (1LL * tmp * base + s[i]) % p;
}
return tmp;
}
ST 表
void ST()
{
lg[0] = -1;
for(int i = 1; i <= n; i++)
{
f[i][0] = read();
lg[i] = lg[i>>1] +1;
}
for(int j = 1; j <= 20; j++)
{
for(int i = 1; i + (1<<j)-1 <= n; i++)
{
f[i][j] = max(f[i][j-1],f[i + (1<<(j-1))][j-1]);
}
}
for(int i = 1; i <= m; i++)
{
l = read(), r = read();
tmp = lg[r-l+1];
printf("%d\n",max(f[l][tmp],f[r-(1<<tmp)+1][tmp]));
}
}
负环
bool fuhuan()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
queue<int> q;
q.push(1); dis[1] = 0; num[1] = 1; vis[1] = 1;
while(!q.empty())
{
int t = q.front(); q.pop(); vis[t] = 0;
for(int i = head[t]; i; i = e[i].net)
{
int to = e[i].to;
if(dis[to] > dis[t] + e[i].w)
{
dis[to] = dis[t] + e[i].w;
num[to]++;
if(num[to] > n) return 0;
if(!vis[to]) { q.push(to); vis[to] = 1;}
}
}
}
return 1;
}
单调栈
void sta()
{
top = 0; sta[++top] = 0;
for(int i = 1; i <= n; i++)
{
while(top && a[sta[top]] >= a[i]) top--;
l[i] = sta[top]; sta[++top] = i;
}
}
乘法逆元
void inv()
{
inv[1] = 1;
for(int i = 2; i <= n; i++)
{
inv[i] = 1LL * (p - p/i) * inv[p % i] % p;
printf("%lld\n",inv[i]);
}
}
tire树
struct tire
{
void insert(char *s)
{
int len = strlen(s+1), p = 1;
for(int i = 0; i <= len; i++)
{
int c = s[i] - 'a';
if(!tr[p][c]) tr[p][c] = ++tot;
p = tr[p][c];
}
end[p] = 1;
}
bool ask(char *s)
{
int len = strlen(s+1), p = 1;
for(int i = 0; i <= len; i++)
{
int c = s[i] - 'a';
if(!tr[p][c]) return 0;
p = tr[p][c];
}
return end[p];
}
}
树剖Lca
struct shupou
{
void get_tree(int x)
{
dep[x] = dep[fa[x]] + 1; siz[x] = 1;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(to = fa[x]) continue;
fa[to] = x;
get_tree(to,x);
siz[x] += siz[to];
if(siz[to] > siz[son[x]]) son[x] = to;
}
}
void dfs(int x,int topp)
{
top[x] = topp; dfn[x] = ++num;
if(son[x]) dfs(son[x],topp);
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(to == fa[x] || to == son[x]) continue;
dfs(to,to);
}
}
int lca(int x,int y)
{
while(top[x] != top[y])
{
if(dep[top[x]] <= dep[top[y]]) swap(x,y);
x = fa[top[x]];
}
return dep[x] <= dep[y] ? x : y;
}
}
线段树
struct Segment_Tree
{
void up(int o){ sum(o) = sum(o<<1) + sum(o<<1|1); }
void cover(int o,int val)
{
sum(o) += (r(o) - l(o) + 1) * val;
tag(o) += val;
}
void down(int o)
{
if(tag(o))
{
cover(o<<1,tag(o));
cover(o<<1|1,tag(o));
tag(o) = 0;
}
}
void build(int o,int L,int R)
{
l(o) = L, r(o) = r;
if(L == R)
{
sum(o) = w[L];
return;
}
int mid = (L + R)>>1;
build(o<<1,L,mid);
build(o<<1|1,mid+1,R);
up(o);
}
void chenge(int o,int L,int R,int val)
{
if(L <= l(o) && R >= r(o))
{
cover(o,val);
return;
}
down(o);
int mid = (l(o) + r(o))>>1;
if(L <= mid) chenge(o<<1,L,R,val);
if(R > mid) chenge(o<<1|1,L,R,val);
up(o);
}
int query(int o,int L,int R)
{
int res = 0;
if(L <= l(o) && R >= r(o)) return sum(o);
down(o);
int mid = (l(o) + r(o))>>1;
if(L <= mid) res += query(o<<1,L,R);
if(R > mid) res += query(o<<1|1,L,R);
return res;
}
void merage(int &x,int y)
{
if(!x) {x = y; return;}
if(!y) return;
tr[x].sum += tr[y].sum;
tr[x].lc = mergae(tr[x].lc,tr[y].lc);
tr[x].rc = mergae(tr[x].rc,tr[y].rc);
}
}
树状数组
struct BIT
{
int lowbit(int x) {return x & -x;}
void chenge(int x,int val)
{
for(; x <= n; x += lowbit(x)) tr[x] += val;
}
int query(int x)
{
int res = 0;
for(; x; x -= lowbit(x)) res += tr[x];
return res;
}
}
单调队列
struct queue
{
int l = 1, r = 0;
for(int i = 1; i <= n; i++)
{
while(l <= r && q[l] < i-k) l++;
while(l <= r && a[q[r]] >= a[i]) r--;
q[++r] = i;
if(i > k) printf("%d\n",q[l]);
}
}
矩阵快速幂,矩阵乘法
struct Matrix
{
struct node
{
int a[2][2];
};
node operator * (node x,node y)
{
node c;
for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) c.a[i][j] = 0;
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
for(int k = 0; k < 2; k++)
{
c.a[i][j] = (c.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
}
}
}
}
node ksm(node a,int b)
{
node res;
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
if(i == j) res.a[i][j] = 1;
else res.a[i][j] = 0;
}
}
for(; b; b >>= 1)
{
if(b & 1) res = res * a % p;
a = a * a % p;
}
return res;
}
}
kmp
struct kmp
{
void init()
{
int j = 0;
for(int i = 2; i <= m; i++)
{
while(j && a[i] != a[j+1]) j = net[j];
if(a[i] == a[j+1]) j++;
net[i] = j;
}
j = 0;
for(int i = 1; i <= n; i++)
{
while(j && b[i] != a[j+1]) j = net[j];
if(b[i] == a[j+1]) j++;
if(j == m) ans++;
}
}
}
spfa
void spfa()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(1); dis[1] = 0; vis[1] = 1;
while(!q.empty())
{
int t= q.front(); q.pop(); vis[t] = 0;
for(int i = head[t]; i; i = e[i].net)
{
int to = e[i].to;
if(dis[to] > dis[t] + e[i].w)
{
dis[to] = dis[t] + e[i].w;
if(!vis[to]) { q.push(to); vis[to] = 1; }
}
}
}
}
二分图染色,匈牙利算法
struct erfentu
{
bool xiongyali(int x)
{
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(!vis[to])
{
vis[to] = 1;
if(!match[to] || dfs(match[to]))
{
match[to] = x;
return 1;
}
}
}
return 0;
}
void dfs(int x,int col)
{
if(flag) return;
col[x] = col;
for(int i = head[x]; i; i = e[i].net)
{
if(!col[e[i].to]) dfs(e[i].to,3-col);
if(col[x] == col[e[i].to]){
flag = 1;
return;
}
}
}
}
exgcd
void exgcd(int a,int b,int &x,int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
exgcd(b,a % b,y,x);
y -= a/b * x;
}
割点,强连通分量
struct tarjain()
{
void tarjain(int x)//割点
{
dfn[x] = low[x] = ++num;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(!dfn[to])
{
tarjain(to);
low[x] = min(low[x],low[to]);
if(low[to] >= dfn[x])
{
flag++;
if(x != rt || flag > 1) cut[x] = true;
}
}
else low[x] = min(low[x],dfn[to]);
}
}
void tarjain(int x)//强连通
{
dfn[x] = low[x] = num++;
sta[++top] = x; vis[x] = 1;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(!dfn[to])
{
tarjain(to);
low[x] = min(low[x],low[to]);
}
else if(vis[to])
{
low[x] = min(low[x],dfn[to]);
}
}
if(dfn[x] == low[x]){
cnt++; int y;
do{
y = sta[top--];
vis[y] = 0;
sum[cnt] += a[y];
c[y] = cnt;
}while(x != y);
}
}
}
manacher算法
void manacher
{
len = len * 2 + 2;
c[0] = '@' , c[1] = '#';
int maxR = -1;//现在最右边的端点
int center = -1;//当前的回文中心
for(int i = 1; i <= len; i++)
{
if(i < maxR) r[i] = min(maxR-i, r[center*2-i]);
else r[i] = 1;
while(c[i+r[i]] == c[i-r[i]]) r[i]++;
if(i + r[i] - 1 > maxR)
{
maxR = i + r[i] - 1;
center = i;
}
ans = max(ans , r[i]);
}
}
左偏树
struct left_tree
{
int merage(int x,int y)
{
if(!x || !y) return x+y;
if(tr[x].val > tr[y].val) swap(x,y);
tr[x].rc = mergae(tr[x].rc,y);
fa[tr[x].rc] = x;
if(tr[tr[x].lc].dis > tr[tr[x].rc].dis) swap(tr[x].lc,tr[x].rc);
tr[x].dis = tr[tr[x].rc].dis + 1;
return x;
}
void del(int x)
{
tr[x].val = -1;
fa[tr[x].lc] = tr[x].lc; fa[tr[x].rc] = tr[x].rc;
fa[x] = merage(tr[x].lc,tr[x].rc);
}
}
主席树
struct charman_tree
{
int insert(int now,int l,int r,int x,int val)
{
int p = ++tot;
tr[p].lc = tr[now].lc;
tr[p].rc = tr[now].rc;
tr[p].sum = tr[now].sum;
if(l == r)
{
tr[p].sum += val;
return p;
}
int mid = (l + r)>>1;
if(x <= mid)
{
tr[p].lc = insert(tr[now].lc,l,mid,x,val);
}
if(x > mid)
{
tr[p].rc = insert(tr[now].rc,mid+1,r,x,val);
}
tr[x].sum = tr[tr[x].lc].sum + tr[tr[x].rc].sum;
return p;
}
int query(int x,int y,int l,int r,int k)
{
if(l == r) return l;
int mid = (l + r)>>1;
int t = tr[tr[x].lc].sum - tr[tr[y].lc].sum;
if(k <= t) return query(tr[x].lc,tr[y].lc,l,mid,k);
else return query(tr[x].rc,tr[y].rc,mid+1,r,k-t);
}
}
01tire
struct 01Tire
{
void insert(int x)
{
for(int i = 1<<30; i; i>>=1)
{
bool c = x & i;
if(tr[fa][c] == 0) tr[fa][c] = ++cnt;
fa = tr[fa][c];
}
}
int query(int x)
{
int res = 0;
for(int i = 1<<30; i; i>>=1)
{
bool c = x & i;
if(tr[fa][c^1])
{
res += i;
fa = tr[fa][c^1];
}
else fa = tr[fa][c];
}
return res;
}
}
Lucas
struct Lucas
{
int C(int n,int m)
{
if(n > m) return 0;
else return jz[n] * inv[m] % p * inv[n-m] % p;
}
int Lucas(int n,int m)
{
if(m == 0) return 1;
return C(n % p,m % p) * Lucas(n/p,m/p) % p;
}
}
CRT
struct CRT
{
void exgcd(int a,int b,int &x,int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
exgcd(b,a % b,y,x);
y -= a/b * x;
}
for(int i = 1; i <= n; i++)
{
M = lcm / m[i];
x = 0; y = 0;
exgcd(M,m[i],x,y);
if(x < 0) x = (x % m[i] + m[i]) % m[i];
ans = (ans + a[i] * M * x) % lcm;
}
}
模拟退火
struct SA
{
void SA()
{
double temp = 3000;
double x = sx;
double y = sy;
while(temp > eps)
{
double xx = x + ((rand()<<1) - RAND_MAX) * temp;
double yy = y + ((rand()<<1) - RAND_MAX) * temp;
double nowans = calc(xx,yy);
double bianhua = nowans - ans;
if(bianhua < 0)
{
ans = nowans;
x = xx; y = yy;
sx = xx; sy = yy;
}
else if(exp(-bianhua / temp) * RAND_MAX > rand())
{
x = xx; y = yy;
}
temp *= d;
}
}
void work()
{
sx = tx / n;
sy = ty / n;
ans = calc(sx,sy);
SA(); SA(); SA(); SA();
}
}
dinic
struct dinic
{
bool bfs()
{
memset(dep , 0 , sizeof(dep));
queue<int> q;
q.push(s); dep[s] = 1;
while(!q.empty())
{
int x = q.front(); q.pop();
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(e[i].w && !dep[to])
{
q.push(to);
dep[to] = dep[x] + 1;
if(to == t) return 1;
}
}
}
return 0;
}
int dinic(int x , int flow)
{
if(x == t) return flow;
int rest = flow , k;
for(int i = head[x]; i && rest; i = e[i].net)
{
int to = e[i].to; int val = e[i].w;
if(val && (dep[to] == dep[x] + 1))
{
k = dinic(to , min(rest , val));
if(!k) dep[to] = 0;
e[i].w -= k; e[i^1].w += k;
rest -= k;
}
}
return flow - rest;
}
void init()
{
while(bfs())
{
while(flow = dinic(s,inf)) ans += flow;
}
}
}
高斯消元
struct Gassus
{
for(int i = 1; i <= n; i++)
{
int pai = i;
while(a[pai][i] == 0 && pai <= n) pai++;
if(pai == n+1)
{
puts("No Solution");
return 0;
}
for(int j = 1; j <= n+1; j++) swap(a[i][j],a[pai][j]);
double rate = a[i][i];
for(int j = 1; j <= n+1; j++)
{
a[i][j] /= rate;
}
for(int j = 1; j <= n; j++)
{
if(i == j) continue;
double rate = a[j][i] / a[i][i];
for(int k = i; k <= n+1; k++)
{
a[j][k] = a[j][k] - rate * a[i][k];
}
}
}
}
线性筛
void YYCH()
{
mu[1] = 1; phi[1] = 1;
for(int i = 2; i <= N-5; i++)
{
if(!check[i])
{
prime[++tot] = i;
mu[i] = -1;
phi[i] = i-1;
}
for(int j = 1; j <= tot && i * prime[j] <= N-5; j++)
{
check[i * prime[j]] = 1;
if(i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else
{
mu[i * prime[j]] = -mu[i];
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
}
杜教筛
int dfsmu(int n){
if(n <= maxn) return sum[n];
if(ans1[n]) return ans1[n];
int ans = 1;
for(int l = 2,r; l <= n; l = r + 1)
{
r = n/(n/l);
ans -= (r-l+1) * dfsmu(n/l);
}
return ans1[n] = ans;
}
int dfsphi(int n){
if(n <= maxn) return tot[n];
if(ans2[n]) return ans2[n];
int ans = n * (n+1) / 2;
for(int l = 2,r; l <= n; l = r + 1)
{
r = n/(n/l);
ans -= (r-l+1) * dfsphi(n/l);
}
return ans2[n] = ans;
}
扫描线
struct Tree
{
struct tree
{
int l,r;
int len,add;
}tr[N<<2];
struct node
{
int l,r;
int h,tag;
node(){}
node(int a,int b,int c,int d){l = a, r = b,h = c,tag = d;}
}line[N<<1];
#define l(o) tr[o].l
#define r(o) tr[o].r
#define add(o) tr[o].add
#define len(o) tr[o].len
bool comp(node a,node b)
{
return a.h < b.h;
}
void up(int o)
{
if(add(o)) len(o) = d[r(o)+1] - d[l(o)];
else len(o) = len(o<<1) + len(o<<1|1);
}
void build(int o,int L,int R)
{
l(o) = L, r(o) = R;
if(L == R)
{
len(o) = 0;
return;
}
int mid = (L + R)>>1;
build(o<<1,L,mid);
build(o<<1|1,mid+1,R);
}
void chenge(int o,int L,int R,int val)
{
if(L <= l(o) && R >= r(o))
{
add(o) += val;
up(o);
return;
}
int mid = (l(o) + r(o))>>1;
if(L <= mid) chenge(o<<1,L,R,val);
if(R > mid) chenge(o<<1|1,L,R,val);
up(o);
}
int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
line[2 * i - 1] = node(x1,x2,y1,1);
line[2 * i] = node(x1,x2,y2,-1);
b[++tot] = x1;
b[++tot] = x2;
}
sort(b+1,b+tot+1);
sort(line+1,line+2*n+1,comp);
num = unique(b+1,b+tot+1)-b-1;
for(int i = 1; i <= 2 * n; i++)
{
int id1 = lower_bound(b+1,b+num+1,line[i].l)-b;
int id2 = lower_bound(b+1,b+num+1,line[i].r)-b;
d[id1] = line[i].l;
d[id2] = line[i].r;
line[i].l = id1;
line[i].r = id2;
}
build(1,1,num);
for(int i = 1; i < 2 * n; i++)
{
chenge(1,line[i].l, line[i].r-1,line[i].tag);
ans += 1LL * tr[1].len * (line[i+1].h - line[i].h);
}
printf("%lld\n",ans);
}
}
点分治
struct dianfenzhi
{
void get_root(int x,int fa)
{
max_siz[x] = 0; siz[x] = 1;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(to == fa || vis[to]) continue;
get_root(to,x);
siz[x] += siz[to];
max_siz[x] = max(max_siz[x],siz[to]);
}
max_siz[x] = max(max_siz[x],sum_siz-siz[x]);
if(max_siz[x] < max_siz[root]) root = x;
}
void get_dis(int x,int fa,int who)
{
a[++cnt] = node(dis[x],who);
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(to == fa || vis[to]) continue;
dis[to] = dis[x] + e[i].w;
get_dis(to,x,who);
}
}
int search(int d)
{
int L = 1, R = cnt, res = 0;
while(L <= R)
{
int mid = (L+R)>>1;
if(a[mid].d >= d)
{
res = mid;
R = mid - 1;
}
else L = mid + 1;
}
return res;
}
void calc(int x,int d)
{
dis[x] = 0; cnt = 0;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(vis[to]) continue;
dis[to] = dis[x] + e[i].w;
get_dis(to,x,to);
}
a[++cnt] = node(0,0);
sort(a + 1, a + cnt + 1, comp);
for(int i = 1; i <= m; i++)
{
if(ans[i]) continue;
int l = 1, r = cnt;
while(l <= cnt && a[l].d + a[r].d < k[i]) l++;
while(l <= cnt && !ans[i])
{
if(k[i] - a[l].d < a[l].d) break;
int id = search(k[i] - a[l].d);
while(a[id].d + a[l].d == k[i] && a[id].wh == a[l].wh) id++;
if(a[l].d + a[id].d == k[i]) ans[i] = 1;
l++;
}
}
}
void slove(int x)
{
calc(x,0); vis[x] = 1;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(vis[to]) continue;
max_siz[0] = n; sum_siz = siz[to]; root = 0;
get_root(to,0); slove(root);
}
}
}
BSGS
struct BSGS
{
LL ksm(LL a, LL b)
{
LL res = 1;
for(; b; b >>= 1)
{
if(b & 1) res = res * a % p;
a = a * a % p;
}
return res;
}
int BSGS(int a,int b,int p)
{
map<LL,int> hash; hash.clear();
int m = (int)sqrt(p);
for(int i = 0; i <= m; i++)
{
LL val = ksm(a,i) * b % p;//b * a ^ i
hash[val] = i;//放入map中
}
a = ksm(a,m);//a ^ m
for(int i = 0; i <= m; i++)
{
LL val = ksm(a,i);//(a^m)^i
int j = hash.find(val) == hash.end() ? -1 : hash[val];//如果没有j就为-1
if(j >= 0 && i * m - j >= 0) return i * m - j;//找到一组解
}
return -1;
}
}