一坨模板
我谔谔,好像重复了几个。
目录:
- 并查集
- 树状数组
- 行列式求值
- 矩阵
- FHQ-Treap
- 快速幂
- 组合数
- 逆元
- 线段树(区改区查)
- 倍增求lca
- kruskal重构树
- 笛卡尔树
- 可持久化Trie
- 主席树:
- 单点修改+单点查询
- 区间第 \(k\) 小
- 区改区查
- 高斯消元
- 点分治
- 树链剖分
- 最短路
- floyd
- dijkstra
- spfa
- tarjan
- 缩点
- 割点
- 割边
- lca
- 另:求三个点的最短距离
- 树上差分
- 中国剩余定理
- BSGS
- 最小生成树
- 欧拉函数
- 线性筛
- dinic求网络最大流
- 费用流(lfy的)
话说什么时候才能自己打费用流啊喂。 - 高维前缀和
- CDQ 分治
- 整体二分
- 考试用的简易对拍
- 线性基
- 后缀排序
- 求 height 数组
1.并查集
struct Disjoint_Set_Union
{
int fa[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void clear(){F(i,1,n) fa[i]=i;}
void merge(int x,int y)
{
int u=find(x);
int v=find(y);
if(u!=v) fa[u]=v;
}
}dsu;
2.树状数组
struct arr_tree
{
int t[N];
int lowbit(int x){return x&(-x);}
void update(int x,int y){for(;x<=siz;x+=lowbit(x)) t[x]+=y;}//siz为值域范围
int ask(int x)
{
int res=0;
for(;x;x-=lowbit(x)) res+=t[x];
return res;
}
il void clear(){F(i,0,n) t[i]=0;}
}T;
3.行列式求值
复杂度 \(O(n^2\log n + n^3)\)。
int a[N][N];
il int sol()
{
int res=1,w=1;
F(i,1,n)
{
F(j,i+1,n)
{
while(a[i][i])
{
int div=a[j][i]/a[i][i];
F(k,i,n) a[j][k]=(a[j][k]-div*a[i][k]%mod+mod)%mod;
sd swap(a[i],a[j]);w=-w;
}
sd swap(a[i],a[j]);w=-w;
}
}
for(int i=1;i<=n;i++) res=a[i][i]*res%mod;
res=w*res;
return (res+mod)%mod;
}
4.矩阵
具体情况需要具体修改。
struct M
{
int a[N][N];
il void clear(){me(a,0);}
il void init(){F(i,1,n) a[i][i]=1;}
int* operator [](int x){return a[x];}
void Swap(int x,int y){F(i,1,n) sd swap(a[x][i],a[y][i]);}//交换两行
void Mul(int x,int k){F(i,1,n) a[x][i]=(a[x][i]*k%mod+mod)%mod;}//把某行乘上k
void Md(int x,int y,int k){F(i,1,n) a[x][i]=((a[x][i]+(a[y][i]*k%mod))%mod+mod)%mod;}//把某行的k倍乘到另一行上
il M operator*(M t)
{
M res;
F(i,1,n) F(j,1,n) res.a[i][j]=0;
F(i,1,n) F(j,1,n) F(k,1,n) res.a[i][j]=(res.a[i][j]+a[i][k]*t.a[k][j]%mod)%mod;
return res;
}
il M operator^(int k)
{
M res,_=*this;
res.init();
while(k)
{
if(k&1)res=res*_;
_=_*_;
k>>=1;
}
return res;
}
};
5.FHQ-Treap
#include<bits/stdc++.h>
#define sd std::
#define int long long
#define inf 0x3f3f3f3f
#define linf 1e18
#define il inline
#define db double
#define ldb long double
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define umap(x,y) sd unordered_map<x,y>
#define pque(x) sd priority_queue<x>
#define X first
#define Y second
#define kg putchar(' ')
#define Fr(a) for(auto it:a)
#define dbg(x) sd cout<<#x<<": "<<x<<sd endl
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
il void put(int x){print(x);putchar('\n');}
il void printk(int x){print(x);kg;}
const int N=1e5+10;
int n;
struct FHQ
{
struct node
{
int key,pri,siz;
int ls,rs;
}t[N];
#define key(k) t[k].key
#define pri(k) t[k].pri
#define ls(k) t[k].ls
#define rs(k) t[k].rs
#define siz(k) t[k].siz
int size=0,rt=0;//size为结点个数,rt为根
void updrt(int u)//更新以 u 为根的Treap的大小
{
siz(u)=siz(ls(u))+siz(rs(u))+1;
}
void split(int u,int x,int &L,int &R)
{
if(!u)
{
L=R=0;
return;
}
if(key(u)<=x) L=u,split(rs(u),x,rs(u),R);
else R=u,split(ls(u),x,L,ls(u));
updrt(u);
}
int merge(int L,int R)
{
if(!L||!R) return L+R;
if(pri(L)>pri(R))
{
rs(L)=merge(rs(L),R);
updrt(L);
return L;
}
else
{
ls(R)=merge(L,ls(R));
updrt(R);
return R;
}
}
void mknwnd(int x)
{
++size;
siz(size)=1;
ls(size)=rs(size)=0;
key(size)=x,pri(size)=rand();
}
int insert(int x)
{
int L,R;
split(rt,x,L,R);
mknwnd(x);
rt=merge(merge(L,size),R);
return size;
}
int del(int x)
{
int L,M,R;
split(rt,x,L,R);
split(L,x-1,L,M);
M=merge(ls(M),rs(M));
rt=merge(merge(L,M),R);
return rt;
}
int delall(int x)//删除所有值为 x 的结点
{
int L,M,R;
split(rt,x,L,R);
split(L,x-1,L,M);
rt=merge(L,R);
return rt;
}
int getrank(int x)
{
int L,R,res;
split(rt,x-1,L,R);
res=siz(L)+1;
rt=merge(L,R);
return res;
}
int kth(int u,int k)
{
if(k==siz(ls(u))+1) return u;
if(k<=siz(ls(u))) return kth(ls(u),k);
return kth(rs(u),k-siz(ls(u))-1);
}
//前驱
int getpre(int x)
{
int L,R,res;
split(rt,x-1,L,R);
res=key(kth(L,siz(L)));
rt=merge(L,R);
return res;
}
//后继
int getsuf(int x)
{
int L,R,res;
split(rt,x,L,R);
res=key(kth(R,1));
rt=merge(L,R);
return res;
}
}Treap;
il void solve()
{
n=read();
while(n--)
{
int op=read(),x=read();
if(op==1) Treap.insert(x);
if(op==2) Treap.del(x);
if(op==3) put(Treap.getrank(x));
if(op==4) put(Treap.key(Treap.kth(Treap.rt,x)));
if(op==5) put(Treap.getpre(x));
if(op==6) put(Treap.getsuf(x));
}
}
signed main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}
6.快速幂
int ksm(int p,int q)
{
if(!q) return 1;
if(q&1) return p*ksm(p,q-1)%mod;
int tmp=ksm(p,q/2)%mod;
return tmp*tmp%mod;
}
无递归版本:
int ksm(int a,int b)
{
int res=1;
for(;b;b>>=1,a=a*a%mod) if(b&1) res=res*a%mod;
return res;
}
7.组合数
- 常见方法
适用范围:\(n\),\(m\) 较小。
时间复杂度:\(O(m)\)。
依据性质:$$\operatorname{C}_nm=\operatorname{C}_n$$$$C_n^m=\frac{n!}{m!(n-m)!}$$
int C(int n,int m)
{
if(m<0||n<m)return 0;
if(m>n-m)m=n-m;
int i,up=1,down=1;
F(i,0,m-1)
{
up=up*(n-i)%mod;
down=down*(i+1)%mod;
}
return up*inv(down)%mod;
}
- 预处理
适用范围:\(n\),\(m\) 在 \(10^7\) 以内,\(mod\) 为质数
时间复杂度:预处理 \(O(n)\),调用 \(O(1)\)。
int jc[N],inv[N];
void prework(int n)
{
inv[0]=jc[0]=inv[1]=1;
F(i,1,n) jc[i]=jc[i-1]*i%mod;
F(i,2,n) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
F(i,1,n) inv[i]=inv[i-1]*inv[i]%mod;
}
int C(int n,int m)
{
if(n<m)return 0;
return jc[n]*inv[m]%mod*inv[n-m]%mod;
}
- 杨辉三角
适用范围:\(n\),\(m\) 在 \(10^3\) 左右。
时间复杂度:预处理 \(O(n^2)\),调用 \(O(1)\)
空间复杂度:\(O(n^2)\)。
int c[N][N];
il void prework(int n)
{
F(i,1,n) F(j,0,i)
if(!j)c[i][j]=1;
else c[i][j]=c[i-1][j]+c[i-1][j-1];
}
- lucas 定理
适用范围:\(n\),\(m\) 在 \(10^{18}\) 以内,\(mod\) 为 \(10^5\) 以内的质数。
时间复杂度:\(O(mod\times \log n)\)。
int lucas(int a,int b)
{
if(a<mod&&b<mod)return C(a,b);
return C(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
8.逆元
- 扩展欧几里得
时间复杂度:\(O(\log n)\)。
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return gcd;
}
il int inv(int a)
{
int x,y;
exgcd(a,mod,x,y);
return (x%mod+mod)%mod;
}
- 费马小定理
适用范围:\(mod\) 为质数,\(a\) 与 \(mod\) 互质。
时间复杂度:\(O(\log n)\)。
il int qpow(int a,int b,int mod)
{
int res=1;
while(b)
{
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
inline int inv(int a)
{
return qpow(a,mod-2,mod);
}
- 递推
适用范围:\(mod\) 为质数。
时间复杂度:预处理 \(O(n)\),调用 \(O(1)\)。
void get_ny(int n)
{
inv[0]=inv[1]=1;
F(i,2,n) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
9.线段树(区改区查)
{
int s[N<<2],lazy[N<<2];
#define ls k<<1
#define rs k<<1|1
void pushup(int k)
{
s[k]=s[ls]+s[rs];
return;
}
void pushdown(int k,int l,int r)
{
if(!lazy[k]) return;
int mid=l+r>>1;
s[ls]+=(mid-l+1)*lazy[k];
lazy[ls]+=lazy[k];
s[rs]+=(r-mid)*lazy[k];
lazy[rs]+=lazy[k];
lazy[k]=0;
}
void built(int k,int l,int r)
{
if(l==r) return s[k]=a[l],void();
int mid=l+r>>1;
built(ls,l,mid);
built(rs,mid+1,r);
pushup(k);
}
void update(int k,int l,int r,int x,int y,int v)
{
if(x<=l&&y>=r)
{
s[k]+=(r-l+1)*v;
lazy[k]+=v;
return;
}
pushdown(k,l,r);
int mid=l+r>>1;
if(x<=mid) update(ls,l,mid,x,y,v);
if(y>mid) update(rs,mid+1,r,x,y,v);
pushup(k);
}
int ask(int k,int l,int r,int x,int y)
{
if(x<=l&&y>=r) return s[k];
pushdown(k,l,r);
int mid=l+r>>1;
int res=0;
if(x<=mid) res+=ask(ls,l,mid,x,y);
if(y>mid) res+=ask(rs,mid+1,r,x,y);
return res;
}
}T;
10.倍增求lca
int dep[N],f[N][logN],vis[N];
void pre(int u,int fa)
{
vis[u]=1;
dep[u]=dep[fa]+1;
f[u][0]=fa;
F(i,0,20) f[u][i+1]=f[f[u][i]][i];
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(vis[v]) continue;
pre(v,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) sd swap(x,y);
f(i,20,0)
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
}
f(i,20,0)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
11.kruskal 重构树
int n,m,cnt;
struct edge{int u,v,dis;}e[N];
bool cmp(edge a,edge b){return a.dis>b.dis;}
struct node{int to,nex;}a[N];
int head[N],tot;
int val[N],ff[N],vis[N];
int fa[N],top[N],son[N];
int siz[N],dep[N];
struct dcr_tree
{
void add(int u,int to)
{
a[++tot].nex=head[u];
a[tot].to=to;
head[u]=tot;
}
int find(int x)
{
if(x==ff[x])return x;
else return ff[x]=find(ff[x]);
}
void dfs1(int u,int pa)
{
siz[u]=1;
vis[u]=1;
for(int i=head[u];i;i=a[i].nex)
{
int to=a[i].to;
if(to==pa) continue;
dep[to]=dep[u]+1; fa[to]=u;
dfs1(to,u);
siz[u]+=siz[to];
if(siz[to]>siz[son[u]])son[u]=to;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
void kruskal()
{
sd sort(e+1,e+1+m,cmp);
F(i,1,n) ff[i]=i;
F(i,1,m)
{
int x=find(e[i].u),y=find(e[i].v);
if(x!=y)
{
val[++cnt]=e[i].dis;
ff[cnt]=ff[x]=ff[y]=cnt;
add(x,cnt);add(cnt,x);
add(y,cnt);add(cnt,y);
}
}
F(i,1,cnt) if(!vis[i])
{
int f=find(i);
dfs1(f,0);
dfs2(f,f);
}
}
int lca(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]>dep[top[v]])u=fa[top[u]];
else v=fa[top[v]];
}
return dep[u]<dep[v]?u:v;
}
}T;
12.笛卡尔树
//下标满足二叉树性质,权值满足小根堆性质
struct dct_tree
{
int a[N],fa[N],ls[N],rs[N];//a数组为权值
int s[N],top;//单调栈维护最右链
void init()
{
s[++top]=1;
}
void built()
{
init();
F(i,2,n)
{
while(top&&a[s[top]]>a[i]) top--;//找到第一个<a[i]的值
if(!top) ls[i]=s[top+1];
else ls[i]=rs[s[top]],rs[s[top]]=i;
s[++top]=i;
}
}
void tra_mid(int x)//中序遍历
{
printk(x);
if(ls[x]) tra_mid(ls[x]);
if(rs[x]) tra_mid(rs[x]);
}
}T;
13.可持久化Trie
是 这道题 的代码中的模板,其他题需要微调。
int s[N],a[N];
struct Trie
{
int t[N*M][2],tag[N*M],root[N],tot=0;
void insert(int x,int k)
{
int q=root[k],p=root[k-1];
f(i,23,0)
{
int c=(x>>i)&1;
if(t[p][0]) t[q][0]=t[p][0];
if(t[p][1]) t[q][1]=t[p][1];
t[q][c]=++tot;
tag[tot]=k;
p=t[p][c];
q=t[q][c];
}
}
int query(int l,int r,int x)
{
int p=root[r],ans=0;
f(i,23,0)
{
int c=(x>>i)&1;
if(t[p][!c]&&tag[t[p][!c]]>=l) {
ans+=1<<i;
p=t[p][!c];
}
else p=t[p][c];
}
return ans;
}
}T;
14.主席树
- 单点修改+区间查询:
`
int a[N];
struct pst_tree
{
struct node
{
int l,r;
int val;
}t[N<<5];
int root[N],tot=0;
#define l(i) t[i].l
#define r(i) t[i].r
#define val(i) t[i].val
int newly(int k)
{
t[++tot]=t[k];
return tot;
}
int built(int k,int l,int r)
{
k=++tot;
if(l==r) return t[k].val=a[l],tot;
int mid=l+r>>1;
l(k)=built(l(k),l,mid);
r(k)=built(r(k),mid+1,r);
return k;
}
int update(int k,int l,int r,int x,int v)
{
k=newly(k);
if(l==r) return val(k)=v,k;
int mid=l+r>>1;
if(x<=mid) l(k)=update(l(k),l,mid,x,v);
else r(k)=update(r(k),mid+1,r,x,v);
return k;
}
int query(int k,int l,int r,int x)
{
if(l==r) return val(k);
int mid=l+r>>1;
if(x<=mid) return query(l(k),l,mid,x);
return query(r(k),mid+1,r,x);
}
}T;
单点修改(a[x]=y):T.root[i]=T.update(T.root[k],1,n,x,y);
区间查询:T.query(T.root[k],1,n,x),T.root[i]=T.root[k];
- 区间第 \(k\) 小:
//第 i 棵线段树的区间[x,y]就代表a[1]~a[i]中数字[x,y]值域内出现了几次。
struct pst_tree
{
struct node
{
int l,r;
int val;
}t[N<<5];
int root[N],tot=0;
#define l(i) t[i].l
#define r(i) t[i].r
#define val(i) t[i].val
int newly(int k)
{
t[++tot]=t[k];
val(tot)++;
return tot;
}
int built(int k,int l,int r)
{
k=++tot;
if(l==r) return k;
int mid=l+r>>1;
l(k)=built(l(k),l,mid);
r(k)=built(r(k),mid+1,r);
return k;
}
int update(int k,int l,int r,int x)
{
k=newly(k);
if(l==r) return k;
int mid=l+r>>1;
if(x<=mid) l(k)=update(l(k),l,mid,x);
else r(k)=update(r(k),mid+1,r,x);
return k;
}
int query(int l,int r,int x,int y,int z)
{
if(l==r) return l;
int val=val(l(y))-val(l(x));
int mid=l+r>>1;
if(val>=z) return query(l,mid,l(x),l(y),z);
else return query(mid+1,r,r(x),r(y),z-val);
}
}T;
存数:T.root[i]=T.update(T.root[i-1],1,cnt,t),t是离散化之后的a[i]
输出:第k小的下标即为T.query(1,cnt,T.root[x-1],T.root[y],z)
il void solve()
{
n=read(),m=read();
F(i,1,n) a[i]=b[i]=read();
sd sort(b+1,b+1+n);
int cnt=sd unique(b+1,b+1+n)-b-1;
T.root[0]=T.built(0,1,cnt);
F(i,1,n)
{
int t=sd lower_bound(b+1,b+1+cnt,a[i])-b;//离散化
T.root[i]=T.update(T.root[i-1],1,cnt,t);
}
F(i,1,m)
{
int x=read(),y=read(),z=read();
put(b[T.query(1,cnt,T.root[x-1],T.root[y],z)]);
}
}
- 区改区查:
int update(int k,int l,int r,int x,int y,int v)
{
k=newly(k);
val(k)+=(MIN(r,y)-MAX(l,x)+1)*v;
if(x<=l&&y>=r)
{
lazy(k)+=v;
return k;
}
int mid=l+r>>1;
if(x<=mid) l(k)=update(l(k),l,mid,x,y,v);
if(y>mid) r(k)=update(r(k),mid+1,r,x,y,v);
return k;
}
int query(int k,int l,int r,int x,int y,int laz)//laz即标记
{
if(x<=l&&y>=r) return val(k)+(r-l+1)*laz;
int mid=l+r>>1,res=0;
if(x<=mid) res+=query(l(k),l,mid,x,y,laz*lazy(k));
if(y>mid) res+=query(r(k),mid+1,r,x,y,laz*lazy(k));
return res;
}
15.高斯消元
void Gauss()
{
F(i,1,n)
{
ma=i;
F(j,1,n)
{
if(fabs(a[j][j])>eps&&j<i) continue;
if(fabs(a[j][i])>fabs(a[ma][i])) ma=j;
}
F(j,1,n+1) swap(a[i][j],a[ma][j]);
if(fabs(a[i][i])<eps) continue;
F(j,1,n)
{
if(i==j) continue;
db rate=a[j][i]/a[i][i];
F(k,i,n+1) a[j][k]-=a[i][k]*rate;
}
}
}
- 异或消元
void Gauss()
{
F(i,0,n-1)
{
ma=i;
F(j,0,n-1)
{
if(a[j][j]&&j<i) continue;
if(abs(a[j][i])>abs(a[ma][i])) ma=j;
}
F(j,0,n) sd swap(a[i][j],a[ma][j]);
if(!a[i][i]) continue;
F(j,0,n-1)
{
if(i==j) continue;
if(!a[j][i]) continue;
F(k,i,n) a[j][k]^=a[i][k];
}
}
}
16.点分治
- 求树上是否有一条边权和为 \(k\) 的路径。
#include<bits/stdc++.h>
#define inf 2e9
#define linf 1e18
//#define int long long
#define db double
#define ldb long double
#define sd std::
#define il inline
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MAX(x,y) (x>y?x:y)
#define MIN(x,y) (x<y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define umap(x,y) sd unorded_map<x,y>
#define pque(x) sd priority_queue<x>
#define pii sd pair<int,int>
#define X first
#define Y second
#define kg putchar(' ')
#define Fr(a) for(auto it:a)
#define dbg(x) sd cout<<#x<<":"<<"\n"
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),x=-x;printt(x);}
il void printk(int x){print(x);kg;}
il void put(int x){print(x);puts("");}
const int N=1e5+10;
int n,m;
struct node
{
int nex;
int to;
int dis;
}a[N<<1];
int q[N];
int head[N],tot;
void add(int u,int v,int w)
{
a[++tot].nex=head[u];
head[u]=tot;
a[tot].to=v;
a[tot].dis=w;
}
int siz[N],weigh[N],vis[N],ans[N];
int root;
void dfs1(int u,int fa,int sum)//求重心
{
weigh[u]=0,siz[u]=1;//weigh[u]为u为根子树中子树最大的节点
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(v==fa||vis[v]) continue;
dfs1(v,u,sum);
siz[u]+=siz[v];
weigh[u]=MAX(weigh[u],siz[v]);
}
weigh[u]=MAX(weigh[u],sum-siz[u]);
if(weigh[u]<weigh[root]) root=u;
}
int dis[N],cnt,d[N];//d和dis数组本质上是一样的,但d数组的下标是时间戳,cnt是时间戳
void dfs2(int u,int fa)
{
d[++cnt]=dis[u];
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(vis[v]||v==fa) continue;
dis[v]=dis[u]+a[i].dis;
dfs2(v,u);
}
}
void get_ans(int u,int val)//val表示加或者减
{
cnt=0;
dfs2(u,0);
sd sort(d+1,d+1+cnt);
F(i,1,m)
{
int s=0,l=1,r=cnt;
while(l<r)
{
if(d[l]+d[r]<=q[i]) s+=r-l,++l;
else r--;
}
l=1,r=cnt;
while(l<r)
{
if(d[l]+d[r]<q[i]) s-=r-l,++l;
else r--;
}
ans[i]+=s*val;
}
}
void gat_ans(int u)
{
dis[u]=0;
vis[u]=1;
get_ans(u,1);
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(vis[v]) continue;
dis[v]=a[i].dis;
get_ans(v,-1);
root=0;
dfs1(v,u,siz[v]);
gat_ans(root);
}
}
il void solve()
{
n=read(),m=read();weigh[0]=n;
F(i,1,n-1)
{
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
F(i,1,m) q[i]=read();
dfs1(1,0,n);
gat_ans(root);
F(i,1,m) puts(ans[i]?"AYE":"NAY");
}
int main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}
17.树链剖分
软件包管理器的操作有 \(u\to v\) 路径的,所以就放这个。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
const int N=200100;
struct node
{
int nex;
int to;
}a[N];
int tot,head[N];
int fa[N],dep[N],size[N];
int son[N],top[N];
int id[N],rev[N],t;
int s[N<<1],lazy[N<<1];//区间和
int ans;
int n,m;
void built(int k,int l,int r)
{
if(l==r)
{
lazy[k]=-1;
s[k]=0;
return;
}
int mid=l+r>>1;
built(k<<1,l,mid);
built(k<<1|1,mid+1,r);
}
void add(int u,int v)
{
a[++tot].nex=head[u];
head[u]=tot;
a[tot].to=v;
}
void dfs1(int u,int da)
{
size[u]=1;
fa[u]=da;
dep[u]=dep[da]+1;
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(v==da) continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
void dfs2(int u,int da)
{
id[u]=++t;
top[u]=da;
if(!son[u]) return;
dfs2(son[u],da);
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void pushdown(int k,int l,int r)
{
if(lazy[k]==-1) return;
int mid=(l+r)>>1;
s[k<<1]=(mid-l+1)*lazy[k];
lazy[k<<1]=lazy[k];
s[k<<1|1]=(r-mid)*lazy[k];
lazy[k<<1|1]=lazy[k];
lazy[k]=-1;
}
void update(int k,int l,int r,int x,int y,int v)
{
if(y<l||x>r) return;
if(x<=l&&y>=r)
{
s[k]=(r-l+1)*v;
lazy[k]=v;
return;
}
pushdown(k,l,r);
int mid=(l+r)>>1;
update(k<<1,l,mid,x,y,v);
update(k<<1|1,mid+1,r,x,y,v);
s[k]=s[k<<1]+s[k<<1|1];
}
int ask(int k,int l,int r,int x,int y)
{
if(y<l||x>r) return 0;
if(x<=l&&y>=r) return s[k];
pushdown(k,l,r);
int mid=(l+r)>>1;
return ask(k<<1,l,mid,x,y)+ask(k<<1|1,mid+1,r,x,y);
}
void lca(int u,int v)
{
int fu=top[u],fv=top[v];
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
std::swap(u,v);
std::swap(fu,fv);
}
update(1,1,n,id[fu],id[u],1);
u=fa[fu];
fu=top[u];
}
if(dep[u]>dep[v]) std::swap(u,v);
update(1,1,n,id[u],id[v],1);
}
void init()
{
dfs1(1,0);
dfs2(1,1);
built(1,1,n);
}
int x;
std::string op;
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d",&x);
add(x+1,i+1);
add(i+1,x+1);
}
init();
scanf("%d",&m);
while(m--)
{
std::cin>>op;
scanf("%d",&x);x++;
int ff=ask(1,1,n,1,n);
if(op[0]=='i')
{
lca(1,x);
printf("%d\n",abs(ff-ask(1,1,n,1,n)));
}
else
{
update(1,1,n,id[x],id[x]+size[x]-1,0);
printf("%d\n",abs(ff-ask(1,1,n,1,n)));
}
}
}
18.最短路
- floyd
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
- dijkstra
struct edge{int v,w;};
struct node{int dis,u;bool operator > (const node& a) const{return dis>a.dis;}};
vector<edge> e[N];
int dis[maxn],vis[N];
priority_queue<node>q;
void dijkstra(int n,int s)
{
memset(dis,0x3f3f3f3f,sizeof(dis));
dis[s]=0;
q.push({0,s});
while(!q.empty())
{
int u=q.top().u;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(auto ed:e[u])
{
int v=ed.v,w=ed.w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
q.push({dis[v],v});
}
}
}
}
- spfa
判断是否有负环
int spfa_dfs(int u)
{
vis[u]=1;
for(int k=f[u];k!=0;k=e[k].next)
{
int v=e[k].v;
int w=e[k].w;
if(d[u]+w<d[v])
{
d[v]=d[u]+w;
if(!vis[v])
if(spfa_dfs(v)) return 1;
else return 1;
}
}
vis[u]=0;
return 0;
}
19.tarjan
- 缩点
#include<cstdio>
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
const int N=1e6+10;
struct node
{
int nex;
int to;
}a[N];
int tot,head[N];
int num,dfn[N],low[N];//时间戳
int top,s[N],vis[N];//栈
int cnt,scc[N],size[N];//强连通分量的个数,强连通分量,每个强连通分量的元素个数
void add(int u,int v)
{
a[++tot].nex=head[u];
head[u]=tot;
a[tot].to=v;
}
void tarjan(int u)
{
dfn[u]=low[u]=++num;
vis[u]=1,s[++top]=u;
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(!dfn[v])//树枝边
{
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);//后向边,横叉边
}
if(dfn[u]==low[u])
{
cnt++;
int y;
do
{
y=s[top--];
vis[y]=0;
scc[y]=cnt;
size[cnt]++;
}while(u!=y)
}
}
- 割点(
vis[u]=1即u为割点)
void tarjan(int u)
{
dfn[u]=low[u]=++num;
for(int i=head[u];i!=-1;i=a[i].nex)
{
int v=a[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v])
/*割点判定1:x 不为树根,存在树枝边 (x,y)(x 为 y 的父亲),如果满足:
dfn[x]<=low[y],x就是割点。*/
{
if(u!=st&&dfn[v]<=dfn[ed]) vis[u]=1;
}
}
else
{
low[u]=min(low[u],dfn[v]);
}
}
}
- 割边(
ans即为割边个数)
void tarjan(int x,int fa)
{
low[x]=dfn[x]=++num;
for(int i=head[x];i!=-1;i=a[i].nex)
{
int v=a[i].to;
if(!dfn[v])
{
tarjan(v,x);
low[x]=min(low[x],low[v]);
if(dfn[x]<low[v]) ans++;
}
else if(v!=fa)
{
low[x]=min(low[x],dfn[v]);
}
}
}
20.LCA
void pre(int u,int fa)
{
vis[u]=1;
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=0;i<20;i++) f[u][i+1]=f[f[u][i]][i];
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(vis[v]) continue;
pre(v,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;i--)
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
}
for(int i=20;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
- 求三个点的最短距离
cin>>x>>y>>z;
int lc1=lca(x,y),lc2=lca(y,z),lc3=lca(x,z);
if(lc1==lc2&&lc2==lc3) cout<<lc1<<" "<<dep[x]+dep[y]+dep[z]-dep[lc3]-(dep[lc1]*2)<<endl;
else if(lc1==lc2) cout<<lc3<<" "<<dep[x]+dep[y]+dep[z]-dep[lc3]-(dep[lc1]*2)<<endl;
else if(lc1==lc3) cout<<lc2<<" "<<dep[x]+dep[y]+dep[z]-dep[lc2]-(dep[lc1]*2)<<endl;
else cout<<lc1<<" "<<(dep[x]+dep[y]+dep[z])-dep[lc1]-(dep[lc2]*2)<<endl;
- 树上差分
int l=lca(x,y);//x~y都+1
d[x]++;
d[y]++;
d[l]--;
d[f[l][0]]--;
统计:
void dfs(int u,int fa)
{
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(v==fa) continue;
dfs(v,u);
d[u]+=d[v];
}
ans=max(ans,d[u]);
}
主函数中:
dfs(1,0)
21.中国剩余定理
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,A[11],B[11];
ll Exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
ll ans=Exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return ans;
}
ll china()
{
ll lcm=1,d,y,x=0;
for(int i=1;i<=n;i++) lcm*=A[i];
for(int i=1;i<=n;i++)
{
ll w=lcm/A[i];
d=Exgcd(A[i],w,d,y);
x=(x+y*w*B[i])%lcm;
}
return (x+lcm)%lcm;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>A[i]>>B[i];
cout<<china();
return 0;
}
- BSGS
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll BSGS(ll a,ll b,ll m)
{
unordered_map<ll,ll> hs;//map会比这个多一个log的复杂度
hs.clear();
ll cur=1,t=sqrt(m)+1;
for(int B=1;B<=t;B++)
{
(cur*=a)%=m;
hs[b*cur%m]=B;
}
ll now=cur;
for(int A=1;A<=t;A++)
{
auto it=hs.find(now);
if(it!=hs.end()) return A*t-it->second;
(now*=cur)%=m;
}
return -1;
}
ll m,a,b;
int main()
{
ios::sync_with_stdio(0);
cin>>m>>a>>b;
int p=BSGS(a,b,m);
if(p==-1) cout<<"no solution";
else cout<<p;
return 0;
}
22.最小生成树
#include<algorithm>
#include<cstdio>
#define int long long
const int N=1e6+10;
int fa[N];
int n,m;
struct node
{
int to;
int nex;
int dis;
}a[N];
bool cmp(node a,node b){return a.dis<b.dis;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int ans,cnt;
void add(int u,int v,int w)
{
a[++m].nex=u;
a[m].to=v;
a[m].dis=w;
}
void kruskal()
{
for(int i=1;i<=m;i++)
{
int u=find(a[i].nex);
int v=find(a[i].to);
if(u==v) continue;
ans+=a[i].dis;
cnt++;
fa[u]=v;
if(cnt==n-1) return printf("%lld",ans),void();
}
puts("-1");
}
int x;
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
scanf("%lld",&x);
if(x) add(i,j,x);
}
for(int i=1;i<=n;i++) fa[i]=i;
std::sort(a+1,a+1+m,cmp);
kruskal();
}
23.欧拉函数
求的是小于n的正整数中与n互质的数的数目。
注意 \(n=1\) 时这个值为 \(1\)。
#define ull unsigned long long
ull ans;
ull init(ull n)
{
for(ull i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
24.线性筛
void pri()
{
//p[i]:能整除i的最小质数,为0表示i是质数
F(i,2,N)
{
if(!p[i]) pri[++cnt]=i;
for(int j=1;pri[j]*i<=N;j++)
{
p[i*pri[j]]=pri[j];
if(!(i%pri[j])) break;
}
}
}
25.dinic求网络最大流
#include<bits/stdc++.h>
#define sd std::
#define int long long
#define inf 0x3f3f3f3f
#define linf 1e18
#define il inline
#define db double
#define ldb long double
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define umap(x,y) sd unordered_map<x,y>
#define pque(x) sd priority_queue<x>
#define X first
#define Y second
#define kg putchar(' ')
#define Fr(a) for(auto it:a)
#define dbg(x) sd cout<<#x<<": "<<x<<sd endl
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
il void put(int x){print(x);putchar('\n');}
il void printk(int x){print(x);kg;}
const int N=1e5+10;
struct node
{
int nex;
int to;
int w;
}a[N];
int tot=1,head[N],now[N];
void add(int u,int v,int w)
{
a[++tot].nex=head[u];
head[u]=tot;
a[tot].to=v;
a[tot].w=w;
}
int d[N];//d为层数
int n,m,s,t;
int bfs()
{
me(d,0);
sd queue<int> q;
q.push(s);
d[s]=1;
now[s]=head[s];
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to,w=a[i].w;
if(w>0&&!d[v])
{
d[v]=d[u]+1;
now[v]=head[v];
if(v==t) return 1;
q.push(v);
}
}
}
return 0;
}
int dfs(int u,int flow)
{
if(u==t) return flow;
int tmp=flow;
for(int i=now[u];i&&tmp;i=a[i].nex)
{
int v=a[i].to,w=a[i].w;
now[u]=i;
if(d[u]+1==d[v]&&w)
{
int k=dfs(v,MIN(tmp,w));
if(!k) d[v]=0;
a[i].w-=k;
a[i^1].w+=k;
tmp-=k;
}
}
return flow-tmp;
}
il void solve()
{
n=read(),m=read(),s=read(),t=read();
F(i,1,m)
{
int x=read(),y=read(),z=read();
add(x,y,z);
add(y,x,0);
}
int ans=0;
while(bfs()) ans+=dfs(s,INT_MAX);
return put(ans);
}
signed main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}
费用流
#include<bits/stdc++.h>
#define arrout(a,n) rep(i,1,n)std::cout<<a[i]<<" "
#define arrin(a,n) rep(i,1,n)a[i]=read()
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define dep(i,x,n) for(int i=x;i>=n;i--)
#define erg(i,x) for(int i=head[x];i;i=e[i].nex)
#define dbg(x) std::cout<<#x<<":"<<x<<" "
#define mem(a,x) memset(a,x,sizeof a)
#define all(x) x.begin(),x.end()
#define arrall(a,n) a+1,a+1+n
#define PII std::pair<int,int>
#define m_p std::make_pair
#define u_b upper_bound
#define l_b lower_bound
#define p_b push_back
#define CD const double
#define CI const int
#define int long long
#define il inline
#define ss second
#define ff first
#define itn int
int read()
{
char ch=getchar();
int r=0,w=1;
while(ch<'0'||ch>'9') w=ch=='-'?-1:w,ch=getchar();
while(ch>='0'&&ch<='9') r=r*10+ch-'0',ch=getchar();
return r*w;
}
CI N=1e5+5,INF=0x3f3f3f3f3f3f3f3f;
int n,m,s,t,cst,tot=1,vis[N],dis[N],now[N],head[N];
struct edge
{
int to,nex,flow,data;
}e[N<<1];
void add(int x,int y,int f,int z)
{
e[++tot].to=y;
e[tot].flow=f;
e[tot].data=z;
e[tot].nex=head[x];
head[x]=tot;
}
bool spfa()
{
std::queue<int> q;
mem(dis,0x3f);
memcpy(now,head,sizeof now);
q.push(s);
dis[s]=0;
vis[s]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
erg(i,x) {
int y=e[i].to,z=e[i].data;
if(e[i].flow<=0) continue;
if(dis[y]>dis[x]+z) {
dis[y]=dis[x]+z;
if(!vis[y]) {
q.push(y);
vis[y]=1;
}
}
}
}
return dis[t]!=INF;
}
int dfs(int x,int flow)
{
if(x==t) return flow;
vis[x]=1;
int tmp=flow;
for(int i=now[x];i&&tmp;i=e[i].nex)
{
int y=e[i].to,z=e[i].data;
if(!e[i].flow||dis[y]!=dis[x]+z||vis[y]) continue;
int k=dfs(y,std::min(tmp,e[i].flow));
cst+=k*z;
e[i].flow-=k;
e[i^1].flow+=k;
tmp-=k;
}
vis[x]=0;
return flow-tmp;
}
int mcmf()
{
int ans=0;
while(spfa())
{
ans+=dfs(s,INF);
}
return ans;
}
signed main()
{
n=read(),m=read(),s=read(),t=read();
rep(i,1,m)
{
int x=read(),y=read(),f=read(),z=read();
add(x,y,f,z);
add(y,x,0,-z);
}
std::cout<<mcmf()<<" "<<cst;
return 0;
}
27.高维前缀和
对于所有的 \(0\le i\le 2^n-1\),求解 \(\sum \limits_{j\subset i} a_j\)
F(j,0,n-1) F(i,0,(1<<n)-1) if(i>>j&1) f[i]+=f[i^(1<<j)];
28.CDQ分治
#include<algorithm>
#include<cstdio>
#define sd std::
#define int long long
#define inf 0x3f3f3f3f
#define linf 1e18
#define il inline
#define db double
#define ldb long double
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define umap(x,y) sd unordered_map<x,y>
#define pque(x) sd priority_queue<x>
#define X first
#define Y second
#define kg putchar(' ')
#define Fr(a) for(auto it:a)
#define dbg(x) sd cout<<#x<<": "<<x<<sd endl
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
il void put(int x){print(x);putchar('\n');}
il void printk(int x){print(x);kg;}
const int N=2e5+10;
int n,k;
struct arr_tree
{
int s[N];
il int lowbit(int x)
{
return x&(-x);
}
il void update(int x,int y)
{
for(;x<=k;x+=lowbit(x)) s[x]+=y;
}
il int ask(int x)
{
int res=0;
for(;x;x-=lowbit(x))
{
res+=s[x];
}
return res;
}
}T;
struct node
{
int a,b,c,cnt,sum;
}x[N],q[N];
int s[N],p[N];
bool cmp1(node a,node b)
{
if(a.a!=b.a) return a.a<b.a;
if(a.b!=b.b) return a.b<b.b;
return a.c<b.c;
}
bool cmp2(node a,node b)
{
if(a.b!=b.b) return a.b<b.b;
return a.c<b.c;
}
int tot,cnt;
void init()//进行排序离散化等
{
sd sort(x+1,x+1+n,cmp1);
F(i,1,n)
{
cnt++;
if(x[i].a!=x[i+1].a||x[i].b!=x[i+1].b||x[i].c!=x[i+1].c)
{
q[++tot].a=x[i].a;
q[tot].b=x[i].b;
q[tot].c=x[i].c;
q[tot].cnt=cnt;
cnt=0;
}
}
}
il void solve(int l,int r)
{
if(l==r) return;
int mid=l+r>>1;
solve(l,mid);
solve(mid+1,r);
sd sort(q+l,q+mid+1,cmp2);
sd sort(q+mid+1,q+r+1,cmp2);
int i=l,j=mid+1;//双指针
while(j<=r)
{
while(i<=mid&&q[i].b<=q[j].b)
{
T.update(q[i].c,q[i].cnt);
i++;
}
q[j].sum+=T.ask(q[j].c);
j++;
}
F(k,l,i-1) T.update(q[k].c,-q[k].cnt);
}
int ans[N];
il void solve()
{
n=read();k=read();
F(i,1,n) x[i].a=read(),x[i].b=read(),x[i].c=read();
init();
solve(1,tot);
F(i,1,tot) ans[q[i].sum+q[i].cnt-1]+=q[i].cnt;
F(i,0,n-1) put(ans[i]);
}
signed main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}
29.整体二分
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define sd std::
//#define int long long
#define inf 0x3f3f3f3f
#define linf 1e18
#define il inline
#define db double
#define ldb long double
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define umap(x,y) sd unordered_map<x,y>
#define pque(x) sd priority_queue<x>
#define X first
#define Y second
#define kg putchar(' ')
#define Fr(a) for(auto it:a)
#define dbg(x) sd cout<<#x<<": "<<x<<sd endl
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
il void put(int x){print(x);putchar('\n');}
il void printk(int x){print(x);kg;}
const int N=1e6+10;
int n,m;
int a[N];
struct arr_tree
{
int s[N];
il int lowbit(int x){return x&(-x);}
il void update(int x,int y){for(;x<=n;x+=lowbit(x)) s[x]+=y;}
il int ask(int x){int res=0;for(;x;x-=lowbit(x)){res+=s[x];}return res;}
}T;
struct query
{
int l,r,k;
int id;
int val;
int op;//op=0表这是数据,op=1代表这是询问
}q[N],q1[N],q2[N];//q1q2用来暂时储存第一类和第二类询问
int ans[N];
void solve(int ql,int qr,int l,int r)//l和r为答案区间,ql和qr为询问区间
{
if(ql>qr) return;
if(l==r)
{
F(i,ql,qr) if(q[i].op) ans[q[i].id]=l;//赋值
return;
}
int mid=l+r>>1;
int c1=0,c2=0;//两种类型的询问的个数
F(i,ql,qr)
{
if(!q[i].op)
{
if(q[i].r<=mid) T.update(q[i].id,1),q1[++c1]=q[i];
else q2[++c2]=q[i];
}
else
{
int ans=T.ask(q[i].r)-T.ask(q[i].l-1);
if(ans>=q[i].k) q1[++c1]=q[i];
else q2[++c2]=q[i],q2[c2].k-=ans;
}
}
F(i,ql,qr) if(!q[i].op&&q[i].r<=mid) T.update(q[i].id,-1);//清空树状数组
F(i,1,c1) q[ql+i-1]=q1[i];
F(i,1,c2) q[ql+i+c1-1]=q2[i];
solve(ql,ql+c1-1,l,mid);
solve(ql+c1,qr,mid+1,r);
}
il void solve()
{
n=read(),m=read();
F(i,1,n) q[i].r=read(),q[i].id=i,q[i].op=0;
F(i,1,m) q[i+n].l=read(),q[i+n].r=read(),q[i+n].k=read(),q[i+n].id=i,q[i+n].op=1;
solve(1,n+m,-inf,inf);
F(i,1,m) put(ans[i]);
}
int main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}
30.对拍
#include<bits/stdc++.h>
using namespace std;
int main() {
int tot=0,k;
scanf("%d",&k);
while(k--) {
system("mkdata.exe");
system("AC.exe");
double st=clock();
system("WA.exe");
double ed=clock();
if(!system("fc AC.out WA.out"))printf("第%d个测试点:Accepted,用时:%.2lfms\n",++tot,ed-st);
else {
printf("第%d个测试点:Wrong Answer \n",++tot);
break;
}
}
return 0;
}
31.线性基
int d[N];//线性基
void insert(int x)
{
f(i,55,0)
{
if(!(x&(1ll<<i))) continue;
if(d[i]) x^=d[i];
else
{
d[i]=x;
break;
}
}
}
32.后缀排序
#include<bits/stdc++.h>
#define sd std::
//#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=5e5+10;
int n,p,V;
char s[N];
int sa[N],id[N],ork[N],rk[N],cnt[N],height[N];
void solve()
{
scanf("%s",s+1);
n=strlen(s+1);
F(i,1,n) cnt[rk[i]=s[i]]++;
V=128;
F(i,1,V) cnt[i]+=cnt[i-1];
f(i,n,1) sa[cnt[rk[i]]--]=i;
for(int w=1;;w<<=1,V=p)
{
int cur=0;
F(i,n-w+1,n) id[++cur]=i;
F(i,1,n) if(sa[i]>w) id[++cur]=sa[i]-w;
F(i,1,V) cnt[i]=0;
F(i,1,n) cnt[rk[i]]++;
F(i,1,V) cnt[i]+=cnt[i-1];
f(i,n,1) sa[cnt[rk[id[i]]]--]=id[i];
F(i,1,n) ork[i]=rk[i];
p=0;
F(i,1,n)
{
if(ork[sa[i]]==ork[sa[i-1]]&&ork[sa[i]+w]==ork[sa[i-1]+w])
{
rk[sa[i]]=p;
}
else rk[sa[i]]=++p;
}
if(p==n) break;
}
F(i,1,n) printk(sa[i]);
}
int main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}
33.求 height 数组
#include<bits/stdc++.h>
#define sd std::
//#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=5e5+10;
int n,p,V;
char s[N];
int sa[N],id[N],ork[N],rk[N],cnt[N],height[N];
void solve()
{
scanf("%s",s+1);
n=strlen(s+1);
F(i,1,n) cnt[rk[i]=s[i]]++;
V=128;
F(i,1,V) cnt[i]+=cnt[i-1];
f(i,n,1) sa[cnt[rk[i]]--]=i;
for(int w=1;;w<<=1,V=p)
{
int cur=0;
F(i,n-w+1,n) id[++cur]=i;
F(i,1,n) if(sa[i]>w) id[++cur]=sa[i]-w;
F(i,1,V) cnt[i]=0;
F(i,1,n) cnt[rk[i]]++;
F(i,1,V) cnt[i]+=cnt[i-1];
f(i,n,1) sa[cnt[rk[id[i]]]--]=id[i];
F(i,1,n) ork[i]=rk[i];
p=0;
F(i,1,n)
{
if(ork[sa[i]]==ork[sa[i-1]]&&ork[sa[i]+w]==ork[sa[i-1]+w])
{
rk[sa[i]]=p;
}
else rk[sa[i]]=++p;
}
if(p==n) break;
}
F(i,1,n)
{
int k=height[rk[i-1]];
if(k) k--;
while(s[i+k]==s[sa[rk[i]-1]+k]) k++;
height[rk[i]+1]=k;
}
F(i,1,n) printk(height[i]);
}
int main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}

浙公网安备 33010602011771号