傻子专用
要是有什么没放上去的,就是忘了或者懒得放了
杂项
杂项
缺省源
#include<bits/stdc++.h>
namespace Mudrock_csy {
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define cerr_time cerr<<clock()*1.0/CLOCKS_PER_SEC<<endl
#define endl '\n'
inline int read() {
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-48;c=getchar();}
return x*f;
}
} using namespace Mudrock_csy;
namespace Mudrock_mod {
const int mod = 998244353 ;
inline int add(int x,int y) {return x+y>=mod?x+y-mod:x+y;}
inline int del(int x,int y) {return x>=y?x-y:x-y+mod;}
inline int mul(int x,int y) {return 1ll*x*y%mod;}
inline void Add(int &x,int y) { x=(x+y>=mod?x+y-mod:x+y); }
inline void Del(int &x,int y) { x=(x>=y?x-y:x-y+mod); }
inline void Mul(int &x,int y) { x=(1ll*x*y%mod); }
inline int power(int x,int t) {
int ans=1; while(t) {
if(t&1) ans=mul(ans,x);
x=mul(x,x); t>>=1;
} return ans ;
}
inline int inv(int x) {return power(x,mod-2);}
} // using namespace Mudrock_mod;
int main()
{
#ifndef Mudrock
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
}
离散化
int ls[MAX];
void lsh(int x[],int n) {
for(int i=1;i<=n;i++)
ls[i]=x[i];
sort(ls+1,ls+n+1);
int m=unique(ls+1,ls+n+1)-ls-1;
for(int i=1;i<=n;i++)
x[i]=lower_bound(ls+1,ls+m+1,x[i])-ls;
}
注意事项:
之前我函数里复制直接用的memcpy,会报错
对于函数中以数组为参数时,是传址而不是传整个数组空间
所以sizeof对应的长度并非x的长度
运行时间
cerr<<clock()*1.0/CLOCKS_PER_SEC<<endl;
随机数
上面那个在Windows下用,下面那个在Linux下用
mt19937 myrand(*(new unsigned));
mt19937 myrand(clock());
inline int rand(int l,int r) { return uniform_int_distribution<int>(l,r)(myrand); }
cout<<rand(-10,10)<<endl;
// 用于生成 l~r 之间的随机数
拿purfer序列建树
int pru[MAX],d[MAX];
int main()
{
int n=10,top=1,mem=0; cout << n << endl ;
for(int i=1;i<=n-1;i++) d[pru[i]=rand(1,n)]++;
for(int i=1;i<=n-1;i++) {
if(!mem) {while(d[top])top++;mem=top;}
cout << pru[i] << " " << mem << endl ;
if(!(--d[pru[i]])&&pru[i]<top) mem=pru[i];
else mem=0,top++;
}
}
对拍
Windows下的,Sleep单位为毫秒,/w 是用来处理多余空格空行的
#include<bits/stdc++.h>
using namespace std;
int main(){
system("g++ data.cpp -o data.exe -O2");
system("g++ mine.cpp -o mine.exe -O2");
system("g++ std.cpp -o std.exe -O2");
int awa=0;
while(233) {
cout<<++awa<<"\n";
system("data.exe > in");
system("std.exe < in > std");
system("mine.exe < in > mine");
if(system("fc mine std /w > nul")) {cout<<"Wrong Answer\n";return 0;}
else cout<<"Accept\n";
}
}
linux下的,usleep单位是微秒,sleep是秒(但不知打为啥往sleep里面塞小数没用)
#include<bits/stdc++.h>
using namespace std;
int main()
{
system("g++ data.cpp -o data.exe -O2 -DMudrock") ;
system("g++ mine.cpp -o mine.exe -O2 -DMudrock") ;
system("g++ std.cpp -o std.exe -O2 -DMudrock") ;
int cnt = 0 ;
while(true) {
cout << (++cnt) << ": " ;
system("./data.exe > in");
system("./std.exe < in > std");
system("./mine.exe < in > mine");
if(system("diff mine std -B -w")) return cout << "Wrong Answer\n" , 0 ;
else cout<<"Accept\n";
}
}
小工具
Windows
编译运行
#include<bits/stdc++.h>
using namespace std;
int main()
{
system("g++ awa.cpp -o awa.exe -std=c++14 -O2 -Wl,--stack=256000000 -DMudrock");
system("awa.exe < in > out");
}
比较
#include<bits/stdc++.h>
using namespace std;
int main()
{
system("g++ awa.cpp -o awa.exe -O2 -Wl,--stack=256000000");
system("awa.exe < example > out");
if(system("fc out ans /w")) cout<<"Wrong Answer\n";
else cout<<"Accept\n";
}
一键测样例
#include<bits/stdc++.h>
using namespace std;
void solve1() {
string s;cin>>s;
int l,r; cin>>l>>r;
for(int i=l;i<=r;i++)
{
string sin=s+to_string(i)+".in",sout=s+to_string(i)+".ans";
string ss="awa.exe < "+sin+" > out";
system(ss.c_str());
ss="fc out "+sout+" /w";
if(system(ss.c_str())) {
cout<<"Wrong Answer "<<i<<endl;return ;
}
}
cout<<"Accept\n";
}
void solve2() {
string s; cin >> s;
string sin=s+".in",sout=s+".ans";
string ss="awa.exe < "+sin+" > out";
system(ss.c_str());
ss="fc out "+sout+" /w";
if(system(ss.c_str())) cout<<"Wrong Answer "<<endl;
else cout<<"Accept\n";
}
int main()
{
system("g++ awa.cpp -o awa -O2 -Wl,--stack=25600000 -DMudrock");
int opt ; cin >> opt ;
if(opt==1) solve1(); else solve2();
}
Linux
编译运行
#include<bits/stdc++.h>
using namespace std;
int main()
{
system("g++ awa.cpp -o awa -O2 -std=c++14 -DMudrock -lm -Wall -fsanitize=address,undefined");
system("awa.exe < in > out");
}
比较
#include<bits/stdc++.h>
using namespace std;
int main()
{
string sin=".in",sout=".ans",s; cin>>s;
system("g++ awa.cpp -o awa -O2 -Wall -std=c++14 -lm -DMudrock -fsanitize=address,undefined");
system(("time ./awa < "+ s+sin +" > out").c_str());
if(system(("diff out "+s+sout+" -B -w").c_str())) cout << "Wrong Answer\n";
else cout << "Accept\n";
}
快读
constexpr auto SIZE(1<<20);
char in[SIZE],out[SIZE],*p1=in,*p2=in,*p3=out;
#define getchar() (p1==p2&&(p2=(p1=in)+fread(in,1,SIZE,stdin),p1==p2)?EOF:*p1++)
#define flush() (fwrite(out,1,p3-out,stdout))
#define putchar(x) (p3==out+SIZE&&(flush(),p3=out),*p3++=(x))
class Flush{public:~Flush(){flush();}}_;
inline int read(){
int x(0);bool f(0);char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar()) f^=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
return f?x=-x:x;
}
inline void write(int x){
x<0?x=-x,putchar('-'):0;static short Sta[50],top(0);
do{Sta[++top]=x%10;x/=10;}while(x);
while(top) putchar(Sta[top--]|48);
putchar('\n');
}
链接
数学
逆元
快速幂
费马小定理 , 仅限 \(mod\) 为素数
inline int inv(int x,int t=mod-2) {
int ans = 1 ; while(t) {
if(t&1) Mul(ans,x) ;
t >>= 1 ; Mul(x,x) ;
} return ans ;
}
exgcd
int exgcd(int a,int b,int &x,int &y) {
if(!b) {
x=1; y=0;
return a;
}
int ans=exgcd(b,a%b,x,y);
int c=x;
x=y;
y=c-a/b*y;
return ans;
}
int inv(int a,int mod) {
int x,y;
exgcd(a,mod,x,y);
return x>0 ? x : x+mod;
}
递推
inv[n]=power(n,mod-2); for(int i=n-1;i;i--) inv[i]=mul(inv[i+1],i+1);
inv[1]=1; for(int i=2;i<mod;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
组合数
A , C , lucas
inline int C(int n,int m) {
if(n<m) return 0; if(!n||!m) return 1;
return mul(fac[n],inv(mul(fac[m],fac[n-m])));
}
int lucas(int n,int m) {
if(m==0) return 1;
return C(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
inline int A(int n,int m) {
if(!n||!m) return 1;
return mul(fac[n],inv(fac[n-m]));
}
exlucas
int A[1010],B[1010];
int exgcd(int a,int b,int &x,int &y) {
if(!b) {
x=1;y=0;
return a;
}
int ans=exgcd(b,a%b,x,y);
int c=x;
x=y;
y=c-a/b*y;
return ans;
}
int inv(int a,int mod) {
int x,y;
exgcd(a,mod,x,y);
return x>0?x:x+mod;
}
int power(int n,int k,int mod) {
int ans=1;
while(k) {
if(k&1) ans=ans*n%mod;
n=n*n%mod;
k>>=1;
}
return ans;
}
int work1(int n,int p,int d) {
if(!n) return 1;
int a=1,b=1;
for(int i=1;i<=p;i++)
if(i%d) a=a*i%p;
a=power(a,n/p,p);
for(int i=p*(n/p);i<=n;i++)
if(i%d) b=b*(i%p)%p;
return work1(n/d,p,d)*a%p*b%p;
}
int work0(int n,int d) {
if(n<d) return 0;
return work0(n/d,d)+(n/d);
}
int work(int n,int m,int p,int d) {
int a=work1(n,p,d);
int b=inv(work1(m,p,d),p);
int c=inv(work1(n-m,p,d),p);
int pow=power(d,(work0(n,d)-work0(m,d)-work0(n-m,d)),p);
return a*b%p*c%p*pow%p;
}
int exlucas(int a,int b,int mod) {
int tot=0;
int qwq=mod;
for(int i=2;i<=sqrt(mod);i++) {
int awa=1;
while(!(qwq%i)) {
awa*=i;
qwq/=i;
}
if(awa>1) {
A[++tot]=awa;
B[tot]=work(a,b,awa,i);
}
}
if(qwq>1) {
A[++tot]=qwq;
B[tot]=work(a,b,qwq,qwq);
}
int ans=0;
for(int i=1;i<=tot;i++) {
int awa=mod/A[i];
int v=inv(awa,A[i]);
ans=(ans+B[i]*awa%mod*v%mod)%mod;
}
return ans%mod;
}
中国剩余定理
crt
int x=0,n,m=1;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
m*=a[i];
}
for(int i=1;i<=n;i++) {
int qwq=m/a[i];
int v=inv(qwq,a[i]);
x=(x+b[i]*qwq%m*v%m)%m;
}
cout<<x%m;
excrt
int n,x,y,m,k,ans;
while(cin>>n) {
bool pd=false;
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i];
m=a[1];ans=b[1];
for(int i=2;i<=n;i++) {
int gcd=exgcd(m,a[i],x,y);
int c=((b[i]-ans)%a[i]+a[i])%a[i] ;
int qwq=a[i]/gcd;
if(c%gcd) {
cout<<-1<<endl;
pd=true;
break;
}
x=x*(c/gcd)%qwq;
ans+=x*m;
m*=qwq;
ans=ans>0?ans:ans+m;
}
if(!pd) cout<<(ans>0?ans%m:ans+m)<<endl;
}
素数相关
判素数
#include<bits/stdc++.h>
using namespace std;
int main()
{
std::ios::sync_with_stdio(false);
std:cin.tie() ;
int n,m;
cin>>n;
for(int i=2;i<=sqrt(n);i++)
if(!(n%i)) {
cout<<"NO \n"<<i<<endl;
return 0;
}
cout<<"YES"<<endl;
}
质因数分解
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
signed main()
{
ios::sync_with_stdio(false); cin.tie(); cout.tie();
int n ; cin >> n ;
for(int i=2;i*i<=n;i++) {
while(!(n%i)) {
n/=i; cout << i << endl ;
}
} if(n!=1) cout << n << endl ;
}
欧拉筛
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e7+50;
int n,tot,prime[MAX];
bool vis[MAX];
int main()
{
cin>>n;
for(int i=2;i<=n;i++) {
if(!vis[i]) prime[++tot]=i;
for(int j=1;j<=tot&&prime[j]*i<=n;j++)
{
vis[i*prime[j]]=true;
if(!(i%prime[j])) break;
}
}
}
不会分类
线筛 $\mu$
int prime[MAX],mu[MAX],tot;
bool vis[MAX];
void ycl()
{
mu[1]=1;
for(int i=2;i<=MMAX;i++)
{
if(!vis[i]) {prime[++tot]=i;mu[i]=-1;}
for(int j=1;j<=tot&&prime[j]*i<=MMAX;j++)
{
vis[prime[j]*i]=true;
if(!(i%prime[j])) {mu[prime[j]*i]=0;break;}
mu[prime[j]*i]=-mu[i];
}
}
}
狄利克雷前缀和
// 前缀和 f*1
for(int i=1;i<=tot;i++)
for(int j=1;prime[i]*j<=MMAX;j++)
f[prime[i]*j]+=f[j];
// 后缀和
for(int i=1;i<=tot;i++)
for(int j=MMAX/prime[i];j;j--)
f[j]+=f[prime[i]*j];
// 前缀差 f*mu
for(int i=1;i<=tot;i++)
for(int j=MMAX/prime[i];j;j--)
f[prime[i]*j]-=f[j];
// 后缀差
for(int i=1;i<=tot;i++)
for(int j=1;prime[i]*j<=MMAX;j++)
f[j]-=f[prime[i]*j];
正整数自然数幂和
namespace Lagrange {
int ycl[Max],fac[Max] ;
int solve(int n,int k)
{
for(int i=1;i<=k+2;i++) ycl[i] = add ( power(i,k) , ycl[i-1] ) ;
if(n<=k+2) return ycl[n] ;
fac[0] = 1 ; for(int i=1;i<=k+2;i++) fac[i] = mul(fac[i-1],i) ;
int ans = 0 , fir = 1 ;
for(int i=1;i<=k+2;i++) Mul(fir,(n-i)) ;
for(int i=1;i<=k+2;i++) {
int mem = mul ( mul ( ycl[i] , fir ) , inv ( mul( fac[i-1] , mul( fac[k+2-i] , (n-i) ) ) ) ) ;
if((k+2-i)&1) Del(ans,mem) ; else Add(ans,mem) ;
}
return ans ;
}
}
高精度
初始化
#define alen a.awa[0]
#define blen b.awa[0]
#define slen s.awa[0]
const int base=10000;
struct _int {
int awa[20000];
_int() {memset(awa,0,sizeof(awa));awa[0]=1;}
};
int power[4]={1,10,100,1000};
void icin(_int &a)
{
string b;
cin>>b;
alen=(b.size()-1)/4+1;
int awa=0;
for(int i=b.size()-1;i>=0;i--,awa%=4)
a.awa[(b.size()-i-1)/4+1]+=(b[i]-48)*power[awa++];
return ;
}
void icout(const _int a)
{
printf("%d",a.awa[alen]);
for(int i=alen-1;i>=1;i--)
printf("%04d",a.awa[i]);
printf("\n");
return ;
}
bool operator < (const _int a,const _int b)
{
if(alen!=blen) return alen<blen;
for(int i=alen;i>=1;i--)
if(a.awa[i]!=b.awa[i]) return a.awa[i]<b.awa[i];
return false;
}
void operator << (_int &a,int b)
{
for(int i=alen;i>=1;i--)
a.awa[i+b]=a.awa[i];
for(int i=b;i>=1;i--)
a.awa[i]=0;
alen+=b;
while(!a.awa[alen]&&alen>1) alen--;
return ;
}
高精 && 高精
_int operator + (const _int a,const _int b)
{
_int s;
slen=max(alen,blen);
int v=0;
for(int i=1;i<=max(alen,blen);i++)
{
s.awa[i]=a.awa[i]+b.awa[i]+v;
v=s.awa[i]/base;
s.awa[i]%=base;
}
if(v) s.awa[++slen]=v;
return s;
}
_int operator - (const _int a,const _int b)
{
_int s;
slen=alen;
int v=0;
for(int i=1;i<=alen;i++)
{
s.awa[i]=a.awa[i]-b.awa[i]-v;
if(s.awa[i]<0)
s.awa[i]+=base,v=1;
else v=0;
}
while(slen>1&&!s.awa[slen]) slen--;
return s;
}
_int operator * (const _int a,const _int b)
{
_int s;
slen=alen+blen;
for(int i=1;i<=alen;i++)
{
int v=0;
for(int j=1;j<=blen;j++)
{
s.awa[i+j-1]+=a.awa[i]*b.awa[j]+v;
v=s.awa[i+j-1]/base;
s.awa[i+j-1]%=base;
}
s.awa[i+blen]+=v;
}
while(slen>1&&!s.awa[slen]) slen--;
return s;
}
_int operator / (const _int a,const _int b)
{
_int s,v;
slen=alen;
for(int i=alen;i>=1;i--)
{
v<<1;
v.awa[1]=a.awa[i];
while(!(v<b))
{
v=v-b;
s.awa[i]++;
}
}
while(slen>1&&!s.awa[slen]) slen--;
return s;
}
_int operator % (const _int a,const _int b)
{
_int v;
for(int i=alen;i>=1;i--)
{
v<<1;
v.awa[1]=a.awa[i];
while(!(v<b)) v=v-b;
}
return v;
}
高精 && 低精
_int operator *(const _int a,const int b) {
int i=1,v=0;
_int ans;
for(i=1;i<=alen;i++) {
ans.awa [i]+=a.awa [i]*b+v;
v=ans.awa [i]/base;
ans.awa[i]%=base;
}
ans.awa [i]=v;
i=alen+2;
while(!ans.awa [i]&&i>1) i--;
ans.awa [0]=i;
return ans;
}
_int operator /(const _int a,const int b) {
_int ans;
int v=0;
for(int i=alen;i>=1;i--) {
v*=base;
v+=a.awa[i];
ans.awa[i]=v/b;
v=v-ans.awa[i]*b;
}
slen=alen;
while(!ans.awa[slen]&&slen>1) slen--;
icout(ans);
return ans;
}
int operator %(const _int a,const int b) {
int v=0;
for(int i=alen;i>=1;i--) {
v*=base;
v+=a.awa[i];
v%=b;
}
return v;
}
图论
杂项
倍增LCA
lg[1]=0;
for(int i=2;i<=n;i++)
lg[i]=lg[i>>1]+1;
int kfa(int u, int step){
for (int i=0;i<=lg[step];i++)
if (step >> i & 1) u = fa[u][i];
return u;
}
for(int i=1;i<=lg[dep[x]];i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
inline int LCA(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]];
if(x==y) return x ;
for(int i=lg[dep[x]];i>=0;i--)
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
RMQ 求 LCA
int lg[MAX],ST[MAX][22],dfn[MAX],dfn_tot;
lg[1]=0;
for(int i=2;i<=n;i++)
lg[i]=lg[i>>1]+1;
int smax(int x,int y) {return dfn[x]<dfn[y] ? x : y;}
int LCA(int x,int y)
{
if(x==y) return x;
if( (x=dfn[x]) > (y=dfn[y]) ) swap(x,y);
int k=lg[y-x++];
return smax(ST[x][k],ST[y-(1<<k)+1][k]);
}
dfn[x]=++dfn_tot;
ST[dfn_tot][0]=fat;
for(int j=1;j<=20;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
ST[i][j]=smax(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);
最短路
dijkstra
priority_queue<pii,vector<pii>,greater<pii>> q;
int dis[MAX];
bool vis[MAX];
void solve(int root)
{
memset(dis,0x7f,sizeof(dis));
dis[root]=0; q.push({dis[root],root});
while(!q.empty()) {
auto k=q.top(); q.pop();
if(vis[k.second]) continue;
vis[k.second]=true;
for(int i=head[k.second];i;i=e[i].nxt) {
int v=e[i].to;
if(!vis[v]&&dis[v]>dis[k.second]+e[i].w) {
dis[v]=dis[k.second]+e[i].w;
q.push({dis[v],v});
}
}
}
}
关于对 priority_queue 的重载:
struct point{
int from,w;
bool operator <(const point &a) const {
return w>a.w;
}
};
priority_queue默认是从大到小
此处对 < 重载 ,w > a.w 时为真
故当 w > a.w 时 < 成立 ,即 node < (node) a
即为 node(a) 在 node 之前
实质上就是 w 小的时候 node 排在前
SPFA
int dis[MAX];
bool vis[MAX];
queue<int> q;
void SPFA(int root)
{
dis[root]=0; q.push(root); vis[root]=true;
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].to;
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w;
if(!vis[v]) q.push(v),vis[v]=true;
}
} vis[u]=false;
}
}
用 \(vis\) 数组判断是否在队列中,每次松弛将所有不在队列中的点加入队列中
最小生成树
Kruskal
稀疏图用
int fa[MAX];
int from(int x)
{
if(x==fa[x]) return x;
return fa[x]=from(fa[x]);
}
struct EDGE{
int from,to,w;
bool operator < (const EDGE &a) const {
return w < a.w ;
};
}e[EMAX];
int kurs() {
int ans=0,tot=0;
iota(fa+1,fa+n+1,1);
sort(e+1,e+m+1);
for(int i=1;i<=m;i++)
{
if(from(e[i].from)==from(e[i].to))
continue;
fa[from(e[i].from)]=e[i].to;
tot++;
ans+=e[i].w;
if(tot==n-1) return ans;
}
return -1;
}
Prim
稠密图用
struct EDGE{
int to,w,next,from;
bool operator < (const EDGE &a) const {
return w > a.w;
}
}e[EMAX*2];
priority_queue<EDGE> q;
int Prim() {
int awa=1;
vis[1]=true;
do {
for(int i=head[awa];i;i=e[i].next)
if(!vis[e[i].to]) q.push(e[i]);
while(vis[q.top().to]&&!q.empty())
q.pop();
if(!q.empty()) {
awa=q.top().to;
vis[awa]=true;
ans+=q.top().w;
}
} while(!q.empty());
for(int i=1;i<=n;i++)
if(!vis[i]) return -1;
return ans;
}
Prim算法正确性证明:
对于图中任意一个连通子图,与外界连接的最短边一定是最小生成树中的一条边
以任意一个点为最初的连通块,选出联通块内与外界联通的最短的一条边加入最小生成树中,并将所连接的点加入此连通块
网络流
二分图定理相关
最大匹配数 = 最小点覆盖 = n - 最大独立集
最大匹配数 : 能连上的最多边数 , 且对于任意一个 \(i\) 保证 \(d_i \le 1\)
最小点覆盖 : 选出最少点使得任意一条边至少有一个端点被选中
最大独立集 : 选中任意两点不相连
EK
int mmin[MAX],pre[MAX];
queue<int> q;
int BFS(int s,int t)
{
memset(pre,0,sizeof(pre));
memset(mmin,0x3f,sizeof(mmin));
q.push(s);
while(!q.empty())
{
int x=q.front(); q.pop();
for(int i=head[x];i;i=e[i].nxt)
{
int v=e[i].to;
if(pre[v]||v==s||!e[i].w) continue;
pre[v]=i; q.push(v); mmin[v]=min(mmin[x],e[i].w);
}
}
if(!pre[t]) return -1;
return mmin[t];
}
int solve(int s,int t)
{
int ans = 0 ;
while(233) {
int k = BFS(s,t);
if(k==-1) break;
int now = t;
ans += k;
while(now!=s) {
e[pre[now]].w-=k; e[pre[now]^1].w+=k;
now = e[pre[now]^1].to ;
}
}
return ans ;
}
Dinic
namespace Dinic
{
int now[MAX],dep[MAX],s,t,ans;
queue<int> q;
bool BFS()
{
memset(dep,0,sizeof(dep)) ;
memcpy(now,head,sizeof(head)) ;
q.push(s) ; dep[s] = 1 ;
while(!q.empty())
{
int x = q.front() ; q.pop() ;
for(int i=head[x];i;i=e[i].nxt)
{
int v = e[i].to ;
if(dep[v]||!e[i].w) continue ;
dep[v] = dep[x] + 1 ;
q.push(v) ;
}
}
return dep[t] ;
}
int DFS(int x,int res)
{
if(x==t) return res ;
int sum = 0 ;
for(int i=now[x];i&&res;i=e[i].nxt)
{
now[x] = i ; int v = e[i].to ;
if(dep[v]!=dep[x]+1||!e[i].w) continue ;
int k = DFS(v,min(res,e[i].w)) ;
if(!k) dep[v] = 0 ;
e[i].w -= k ; e[i^1].w += k ;
sum += k ; res -= k ;
}
return sum ;
}
int solve(int S,int T)
{
s = S ; t = T ;
int ans = 0 ;
while(BFS()) ans += DFS(s,inf) ;
return ans ;
}
}
EK费用流
namespace EK_cost
{
int pre[MAX],dis[MAX];
bool vis[MAX];
queue<int> q;
bool SPFA(int s,int t)
{
memset(pre,0,sizeof(pre));
memset(dis,0x3f,sizeof(dis));
dis[s]=0; q.push(s); vis[s]=true;
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=head[u];i;i=e[i].nxt) {
if(!e[i].flow) continue;
int v=e[i].to;
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w; pre[v]=i;
if(!vis[v]) q.push(v),vis[v]=true;
}
} vis[u]=false;
}
if(!pre[t]) return false;
return true;
}
pii solve(int s,int t)
{
pii ans = {0,0} ;
while(SPFA(s,t)) {
int now = t , mmin = inf ;
while(now!=s) {
mmin=min(mmin,e[pre[now]].flow);
now=e[pre[now]^1].to;
} now=t;
ans.first+=mmin; ans.second+=mmin*dis[t];
while(now!=s) {
e[pre[now]].flow -= mmin; e[pre[now]^1].flow += mmin;
now = e[pre[now]^1].to ;
}
}
return ans ;
}
}
zkw 费用流
namespace Dinic_cost
{
int dis[MAX],now[MAX],s,t ;
bool vis[MAX] ;
queue<int> q ;
bool SPFA()
{
memset(dis,0x3f,sizeof(dis)) ;
memcpy(now,head,sizeof(head)) ;
q.push(s) ; vis[s] = true ; dis[s] = 0 ;
while(!q.empty())
{
int u = q.front() ; q.pop() ;
for(int i=head[u];i;i=e[i].nxt) {
int v = e[i].to ;
if(!e[i].flow) continue ;
if(dis[u]+e[i].w<dis[v]) {
dis[v] = dis[u] + e[i].w ;
if(!vis[v]) q.push(v) , vis[v] = true ;
}
} vis[u] = false ;
}
return dis[t]!=dis[0] ;
}
int DFS(int x,int res)
{
if(x==t) return res ;
int sum = 0 ; vis[x] = true ;
for(int i=now[x];i&&res;i=e[i].nxt) {
int v = e[i].to ; now[x] = i ;
if(vis[v]||!e[i].flow||dis[v]!=dis[x]+e[i].w) continue ;
int k = DFS(v,min(res,e[i].flow)) ;
sum += k ; res -= k ;
e[i].flow -= k ; e[i^1].flow += k ;
} vis[x] = false ; return sum ;
}
pii solve(int S,int T)
{
s = S ; t = T ; pii ans = {0,0} ;
while(SPFA()) {
int k = DFS(s,inf) ;
ans.first += k ;
ans.second += k * dis[t] ;
}
return ans ;
}
}
数据结构
树状数组
struct BIT {
int num[MAX],n;
inline int lowbit(int x) { return x&(-x); }
inline void add(int x,int k) { while(x<=n) num[x]+=k,x+=lowbit(x); }
inline int check(int x ) { int ans=0; while(x) ans+=num[x],x-=lowbit(x); return ans; }
inline int find(int l,int r) { return check(r)-check(l-1); }
}bit;
线段树(加乘懒标记)
struct Stree {
#define lson (x<<1)
#define rson (x<<1|1)
#define mid ((l+r)>>1)
int num[MAX*4];
int lazt_add[MAX*4],lazt_mul[MAX*4];
void update(int x) { num[x]=add(num[lson],num[rson]); }
void pushdown(int x,int l,int r) {
if(lazt_mul[x]!=1) {
Mul(lazt_mul[lson],lazt_mul[x]);
Mul(lazt_mul[rson],lazt_mul[x]);
Mul(num[lson],lazt_mul[x]); Mul(num[rson],lazt_mul[x]);
Mul(lazt_add[lson],lazt_mul[x]);
Mul(lazt_add[rson],lazt_mul[x]);
lazt_mul[x]=1;
}
if(lazt_add[x]!=0) {
Add(num[lson],mul(mid-l+1,lazt_add[x]));
Add(num[rson],mul(r-mid,lazt_add[x]));
Add(lazt_add[lson],lazt_add[x]);
Add(lazt_add[rson],lazt_add[x]);
lazt_add[x]=0;
}
}
void build(int x,int l,int r)
{
lazt_add[x]=0; lazt_mul[x]=1;
if(l==r) {num[x]=sta[l];return ;}
build(lson,l,mid); build(rson,mid+1,r);
update(x);
}
void t_add(int x,int l,int r,int tl,int tr,int k)
{
if(l>tr||r<tl) return ;
if(l>=tl&&r<=tr) { Add(num[x],mul(r-l+1,k)); Add(lazt_add[x],k); return ; }
pushdown(x,l,r);
t_add(lson,l,mid,tl,tr,k); t_add(rson,mid+1,r,tl,tr,k);
update(x);
}
void t_mul(int x,int l,int r,int tl,int tr,int k)
{
if(l>tr||r<tl) return ;
if(l>=tl&&r<=tr) { Mul(num[x],k); Mul(lazt_add[x],k); Mul(lazt_mul[x],k); return ; }
pushdown(x,l,r);
t_mul(lson,l,mid,tl,tr,k); t_mul(rson,mid+1,r,tl,tr,k);
update(x);
}
int find(int x,int l,int r,int tl,int tr)
{
if(l>tr||r<tl) return 0;
if(l>=tl&&r<=tr) return num[x];
pushdown(x,l,r);
return add( find(lson,l,mid,tl,tr) , find(rson,mid+1,r,tl,tr) );
}
#undef lson
#undef rson
#undef mid
}tree;
权值线段树(LJJ代码)
struct Stree{
#define lson ls[x]
#define rson rs[x]
#define mid ((l+r)>>1)
int tot=0;
int num[MAX*50],ls[MAX*50],rs[MAX*50];
double sum[MAX*50];
Stree() {
memset(num,0,sizeof(num));
memset(ls,0,sizeof(ls));
memset(rs,0,sizeof(rs));
memset(sum,0,sizeof(sum));
}
void add(int &x,int l,int r,int t,int k)
{
if(!x) x=++tot;
if(l==r) {num[x]+=k;sum[x]=log(l)*(double)num[x];return ;}
if(t<=mid) add(lson,l,mid,t,k);
else add(rson,mid+1,r,t,k);
num[x]=num[lson]+num[rson]; sum[x]=sum[lson]+sum[rson];
}
int merge(int x,int y,int l,int r)
{
if(!x||!y) return x+y;
if(l==r) return (num[x]+=num[y],sum[x]+=sum[y],x);
lson=merge(ls[x],ls[y],l,mid);
rson=merge(rs[x],rs[y],mid+1,r);
num[x]=num[lson]+num[rson]; sum[x]=sum[lson]+sum[rson];
return x;
}
int clear_min(int &x,int l,int r,int t)
{
if(!x||l>=t) return 0;
if(r<t) {int k=num[x];x=0;return k;}
return clear_min(lson,l,mid,t)+clear_min(rson,mid+1,r,t);
}
int clear_max(int &x,int l,int r,int t)
{
if(!x||r<=t) return 0;
if(l>t) {int k=num[x];x=0;return k;}
return clear_max(lson,l,mid,t)+clear_max(rson,mid+1,r,t);
}
int check(int x,int l,int r,int t)
{
if(l==r) return l;
if(num[lson]>=t) return check(lson,l,mid,t);
else return check(rson,mid+1,r,t-num[lson]);
}
#undef lson
#undef rson
#undef mid
}tree;
clear_min/max 没有更新值是因为该题目中后面会接一个 add , 后面更新值就可以了
连边后记得用并查集找根 , 否则会出现 a->b , b->c 但 ac 不相连的问题
树链剖分
int son[MAX],siz[MAX],fa[MAX],dep[MAX];
void dfs1(int x,int fat)
{
son[x]=0; siz[x]=1; fa[x]=fat; dep[x]=dep[fat]+1;
for(int v:vec[x]) {
if(v==fat) continue;
dfs1(v,x);
siz[x]+=siz[v];
son[x]=siz[v]>siz[son[x]]?v:son[x];
}
}
int mp[MAX],dfn[MAX],top[MAX],dfn_num;
void dfs2(int x,int fat)
{
top[x]=fat; mp[dfn[x]=++dfn_num]=x;
if(son[x]) dfs2(son[x],fat);
for(int v:vec[x]) {
if(dfn[v]) continue;
dfs2(v,v);
}
}
struct Stree {
#define lson (x<<1)
#define rson (x<<1|1)
#define mid ((l+r)>>1)
int num[MAX*4],lazt[MAX*4];
void pushdown(int x,int l,int r)
{
if(!lazt[x]) return ;
Add(lazt[lson],lazt[x]); Add(lazt[rson],lazt[x]);
Add(num[lson],mul(lazt[x],(mid-l+1)));
Add(num[rson],mul(lazt[x],(r-mid)));
lazt[x]=0;
}
void build(int x,int l,int r)
{
if(l==r) {num[x]=sta[mp[l]]%mod;return ;}
build(lson,l,mid); build(rson,mid+1,r);
num[x]=::add(num[lson],num[rson]);
}
void add(int x,int l,int r,int tl,int tr,int k)
{
if(l>tr||r<tl) return ;
if(l>=tl&&r<=tr) { Add(num[x],mul(k,(r-l+1))); Add(lazt[x],k); return; }
pushdown(x,l,r);
add(lson,l,mid,tl,tr,k); add(rson,mid+1,r,tl,tr,k);
num[x]=::add(num[lson],num[rson]);
}
int find(int x,int l,int r,int tl,int tr)
{
if(l>tr||r<tl) return 0;
if(l>=tl&&r<=tr) return num[x];
pushdown(x,l,r);
return ::add(find(lson,l,mid,tl,tr),find(rson,mid+1,r,tl,tr));
}
#undef lson
#undef rson
#undef mid
}tree;
int n;
void spadd(int x,int y,int w)
{
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
tree.add(1,1,n,dfn[top[x]],dfn[x],w);
x=fa[top[x]];
}
if(dfn[x]>dfn[y]) swap(x,y);
tree.add(1,1,n,dfn[x],dfn[y],w);
}
int spfind(int x,int y) {
int ans = 0;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
Add(ans,tree.find(1,1,n,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dfn[x]>dfn[y]) swap(x,y);
Add(ans,tree.find(1,1,n,dfn[x],dfn[y]));
return ans ;
}
可持久化线段树
struct Stree {
#define lson ls[x]
#define rson rs[x]
#define mid ((l+r)>>1)
int tot;
int num[MAX*100],ls[MAX*100],rs[MAX*100];
void build(int &x,int l,int r)
{
if(!x) x=++tot;
if(l==r) {num[x]=sta[l];return ;}
build(lson,l,mid); build(rson,mid+1,r);
}
void copy(int &x)
{
num[++tot]=num[x];
ls[tot]=ls[x];
rs[tot]=rs[x];
x=tot;
}
void add(int &x,int l,int r,int t,int k)
{
copy(x);
if(l==r) {num[x]=k;return ;}
if(t<=mid) add(lson,l,mid,t,k);
else add(rson,mid+1,r,t,k);
}
int find(int x,int l,int r,int t)
{
if(l==r) return num[x];
if(t<=mid) return find(lson,l,mid,t);
else return find(rson,mid+1,r,t);
}
#undef lson
#undef rson
#undef mid
} tree ;
主席树
struct Stree {
#define lson ls[x]
#define rson rs[x]
#define mid ((l+r)>>1)
int tot;
int num[MAX*20],ls[MAX*20],rs[MAX*20];
void copy(int &x) {
num[++tot]=num[x];
ls[tot]=ls[x]; rs[tot]=rs[x];
x=tot;
}
void add(int &x,int l,int r,int t)
{
copy(x);
if(l==r) {num[x]++;return ;}
if(t<=mid) add(lson,l,mid,t);
else add(rson,mid+1,r,t);
num[x]=num[lson]+num[rson];
}
int check(int x,int y,int l,int r,int k)
{
if(l==r) return l;
if(num[ls[y]]-num[ls[x]]>=k) return check(ls[x],ls[y],l,mid,k);
else return check(rs[x],rs[y],mid+1,r,k-(num[ls[y]]-num[ls[x]]));
}
#undef lson
#undef rson
#undef mid
} tree;
树状数组套权值线段树
struct TREE{
#define lson ls[x]
#define rson rs[x]
#define mid ((l+r)>>1)
int tot;
int ls[MAX*200],rs[MAX*200],size[MAX*200];
void csh() {
tot=0;
memset(ls,0,sizeof(ls));
memset(rs,0,sizeof(rs));
memset(size,0,sizeof(size));
}
void add(int &x,int l,int r,int k)
{
if(!x) x=++tot;
if(l==r) {
size[x]++;
return ;
}
if(k<=mid) add(lson,l,mid,k);
else add(rson,mid+1,r,k);
size[x]=size[lson]+size[rson];
return ;
}
void del(int &x,int l,int r,int k)
{
if(l==r) {
if(size[x]==1) x=0;
else size[x]--;
return ;
}
if(k<=mid) del(lson,l,mid,k);
else del(rson,mid+1,r,k);
size[x]=size[lson]+size[rson];
return ;
}
int query(int l,int r,int k)
{
if(l==r) return l;
int tot=0;
for(int i:tr[pd])
tot+=size[ls[i]];
for(int i:tl[pd])
tot-=size[ls[i]];
if(k<=tot) {
tl[!pd].clear();tr[!pd].clear();
for(int i:tr[pd])
tr[!pd].push_back(ls[i]);
for(int i:tl[pd])
tl[!pd].push_back(ls[i]);
pd=!pd;
return query(l,mid,k);
}
else {
tl[!pd].clear();tr[!pd].clear();
for(int i:tr[pd])
tr[!pd].push_back(rs[i]);
for(int i:tl[pd])
tl[!pd].push_back(rs[i]);
pd=!pd;
return query(mid+1,r,k-tot);
}
}
#undef mid
}tree;
inline int lowbit(int x) {return (-x)&x;}
int main()
{
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j+=lowbit(j))
tree.add(root[j],1,m,awa[i]);
for(int T=1;T<=t;T++)
{
if(q[T].opt=='Q') {
int l=q[T].c[0],r=q[T].c[1];
tr[pd].clear();tl[pd].clear();
for(int i=r;i;i-=lowbit(i))
tr[pd].push_back(root[i]);
for(int i=l-1;i;i-=lowbit(i))
tl[pd].push_back(root[i]);
cout<<fls[tree.query(1,m,q[T].c[2])]<<endl;
}
else {
int k=q[T].c[0],t=q[T].c[1];
for(int i=k;i<=n;i+=lowbit(i))
{
tree.del(root[i],1,m,awa[k]);
tree.add(root[i],1,m,t);
}
awa[k]=t;
}
}
}
平衡树
字符串
hash
const int base=233;
int hs[MAX],power[MAX];
inline int find(int l,int r) {return del(hs[r],mul(hs[l-1],power[r-l+1]));}
power[0]=1; for(int i=1;i<=n;i++) power[i]=mul(power[i-1],base);
for(int i=1;i<=n;i++) hs[i]=add(mul(hs[i-1],base),s[i]);
AC自动机
struct TREE{
int son[30];
int fail,num;
bool end;
}tree[MAX];
int tot,ans;
int build(string s)
{
int root=0;
for(int i=0;i<s.size();i++)
{
if(!tree[root].son[s[i]-'a'])
tree[root].son[s[i]-'a']=++tot;
root=tree[root].son[s[i]-'a'];
}
tree[root].end=true;
return root;
}
queue<int> q;
void fail_build()
{
for(int i=0;i<26;i++)
if(tree[0].son[i]) {
tree[tree[0].son[i]].fail=0;
q.push(tree[0].son[i]);
}
while(!q.empty())
{
int root=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(tree[root].son[i]) {
tree[tree[root].son[i]].fail=tree[tree[root].fail].son[i];
q.push(tree[root].son[i]);
}
else tree[root].son[i]=tree[tree[root].fail].son[i];
}
}
}
void find(string s) {
cin>>s;
int root=0;
for(int i=0;i<s.size();i++)
{
root=tree[root].son[s[i]-'a'];
for(int j=root;j;j=tree[j].fail)
{
if(tree[j].end) tree[j].num++;
ans=max(ans,tree[j].num);
}
}
}
后缀数组
char s[MAX];
int x[MAX],y[MAX],t[MAX],sa[MAX],hei[MAX];
void Qsort(int n,int m)
{
for(int i=1;i<=m;i++) t[i]=0;
for(int i=1;i<=n;i++) t[x[i]]++;
for(int i=2;i<=m;i++) t[i]+=t[i-1];
for(int i=n;i>=1;i--) sa[t[x[y[i]]]--]=y[i];
}
void SA(int n)
{
for(int i=1;i<=n;i++) x[i] = s[i]-'a'+1 ;
iota(y+1,y+n+1,1);
int m = 'z'+1 ; Qsort(n,m);
for(int k=1;k<=n;k<<=1)
{
int num = 0;
for(int i=n-k+1;i<=n;i++) y[++num] = i;
for(int i=1;i<=n;i++) if(sa[i]>k) y[++num]=sa[i]-k;
Qsort(n,m); swap(x,y);
num = x[sa[1]] = 1 ;
for(int i=2;i<=n;i++)
x[sa[i]] = (y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
if(num==n) break; else m = num ;
}
for(int i=1,k=0;i<=n;i++)
{
if(k) k-- ;
while(s[i+k]==s[sa[x[i]-1]+k]) k++;
hei[x[i]] = k ;
}
}
PAM
namespace PAM
{
int cnt,last ;
int son[MAX][26],len[MAX],fail[MAX],size[MAX];
void csh(int n)
{
cnt = fail[0] = 1 ;
len[1] = -1 ;
}
int getfail(int k,int now) {
while(s[k-len[now]-1]!=s[k]) now = fail[now];
return now ;
}
void insert(int k)
{
int c = s[k]-'a' ;
last = getfail(k,last) ;
if(!son[last][c]) {
fail[++cnt] = son[getfail(k,fail[last])][c] ;
son[last][c] = cnt ;
len[cnt] = len[last]+2 ;
}
last = son[last][c];
size[last] ++ ;
}
}
SAM
namespace SAM
{
int last=1,cnt=1;
int son[MAX][26],len[MAX],fa[MAX];
void insert(int c)
{
int p = last , np = last = ++cnt ;
len[np] = len[p] + 1 ;
for(;p&&!son[p][c];p=fa[p]) son[p][c] = np ;
if(!p) fa[np] = 1 ;
else {
int q = son[p][c] ;
if(len[q]==len[p]+1) fa[np] = q ;
else {
int nq = ++cnt ;
fa[nq] = fa[q] ;
memcpy(son[nq],son[q],sizeof(son[q])) ;
fa[q] = fa[np] = nq ;
len[nq] = len[p] + 1 ;
for(;son[p][c]==q;p=fa[p]) son[p][c] = nq ;
}
}
}
}