模板
数学
组合数学
快速取模
#define ull unsigned long long
#define ui128 __uint128_t
struct Barrett{
ull d;ui128 m;
void init(ull _d){
d=_d,m=(((ui128)(1)<<64)/d);
}
}mod;
ull operator %(ull a,Barrett mod){
ull w=(mod.m*a)>>64;w=a-w*mod.d;
if(w>=mod.d)w-=mod.d;return w;
}
光速幂
p1[0]=p2[0]=1,S=sqrt(a)+1;
for(int i=1;i<=S;i++) p1[i]=p1[i-1]*a%mod;
for(int i=1;i<=S;i++) p2[i]=p2[i-1]*p1[S]%mod;
while(T--) cin>>b,cout<<p1[b%S]*p2[b/S]%mod<<" ";
组合数
void init(){jc[0]=1;for(int i=1;i<N;i++) jc[i]=jc[i-1]*i%mod;}
ll qp(ll a,ll b){ll ct=1;while(b){if(b&1) ct=ct*a%mod;b>>=1,a=a*a%mod;}return ct;}
ll C(ll n,ll m){return jc[n]*qp(jc[n-m]*jc[m]%mod,mod-2)%mod;}
组合数 O(m)
ll qp(ll a,ll b){ll ct=1;while(b){if(b&1) ct=ct*a%mod;b>>=1,a=a*a%mod;}return ct;}
ll C(ll n,ll m){
ll ct=1,t=1;if(n<m) return 0;
for(int i=1;i<=m;i++) (ct*=(n-i+1)%mod)%=mod,(t*=i)%=mod;
return ct*qp(t,mod-2)%mod;
}
组合数(卡常)
ll qp(ll a,ll b){ll ct=1;while(b){if(b&1) ct=ct*a%mod;b>>=1,a=a*a%mod;}return ct;}
ll C(ll m,ll n){return jc[n]*inv[m]%mod*inv[n-m]%mod;}
void init(){
jc[0]=1;for(int i=1;i<=n;i++) jc[i]=jc[i-1]*i%mod;
inv[n]=qp(jc[n],mod-2);
for(int i=n-1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
lucas
ll T,n,m,p,jc[N],inv[N];
ll Lucas(ll n,ll m,ll p){
if(n<m) return 0;
if(n<p) return jc[n]*inv[m]%p*inv[n-m]%p;
return Lucas(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
ll qp(ll a,ll b,ll ct=1){while(b){if(b&1) ct=ct*a%p;a=a*a%p,b>>=1;}return ct;}
void init(){
for(int i=1;i<=n+m;i++) jc[i]=jc[i-1]*i%p;
inv[min(p-1,n+m)]=qp(jc[min(p-1,n+m)],p-2);
for(int i=min(p-1,n+m)-1;~i;i--) inv[i]=inv[i+1]*(i+1)%p;
}
逆元
for(ll i=2;i<=n;i++) dp[i]=(p-p/i)*dp[p%i]%p;
exgcd
ll T,a,b,c,d,x,y,k,dx,dy;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1,y=0;return a;}
ll d=exgcd(b,a%b,y,x);y-=a/b*x;
return d;
}
void solve(){
cin>>a>>b>>c;d=exgcd(a,b,x,y);
if(c%d){cout<<"-1\n";continue;}
(x*=c)/=d,(y*=c)/=d;
dx=abs(b/d),dy=abs(a/d),k=ceil((1.0-x)/dx);
x+=dx*k,y-=dy*k;
if(y<=0){
cout<<x<<" ";k=ceil((1.0-y)/dy);
y+=dy*k,x-=dx*k;
cout<<y<<"\n";
}else cout<<(y-1)/dy+1<<" "<<x<<" "<<(y-1)%dy+1<<" "<<x+(y-1)/dy*dx<<" "<<y<<"\n";
}
qp+exgcd+BSGS
map<ll,ll> mp;
ll qp(ll a,ll b,ll ct=1){while(b){if(b&1) ct=ct*a%p;a=a*a%p,b>>=1;}return ct;}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1,y=0;return a;}
ll t=exgcd(b,a%b,y,x);y-=a/b*x;return t;
}
void solve2(ll a,ll b,ll p){
ll t=exgcd(a,p,x,y);p/=t;
if(!(b%t)) cout<<((x*b/t)%p+p)%p<<"\n";
else cout<<"Orz, I cannot find x!\n";
}
void BS(ll a,ll b,ll p){for(int i=0;i<=m;i++) mp[b]=i,(b*=a)%=p;}
void GS(ll a,ll b,ll p,ll t=1){
if(!a&&!b){cout<<"1\n";return;}
if(!a){cout<<"Orz, I cannot find x!\n";return;}
ll ct=qp(a,m);
for(int i=1;i<=m;i++)
if(mp[(t*=ct)%=p]){cout<<i*m-mp[t]<<"\n";return;}
cout<<"Orz, I cannot find x!\n";
}
void solve3(ll a,ll b,ll p){a%=p,b%=p,m=ceil(sqrt(p)),mp.clear(),BS(a,b,p),GS(a,b,p);}
excrt
#define i128 __int128
ll n,a,b;
i128 x,y,A=1,B;
i128 exgcd(i128 a,i128 b,i128 &x,i128 &y){
if(!b){x=1,y=0;return a;}
ll d=exgcd(b,a%b,y,x);
y-=a/b*x;return d;
}
ll solve(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a>>b;
i128 d=exgcd(A,(i128)a,x,y);
x*=B-b,y*=B-b;x/=d,y/=d;
B-=A*x,A=A/d*a;((B%=A)+=A)%=A;
}
return (ll)((B%A+A)%A);
}
Miller-Rabin+Pollard-Rho
ll T,n,mx;
ll qp(ll a,ll b,ll mod,ll ct=1){while(b){if(b&1) ct=(__int128)ct*a%mod;a=(__int128)a*a%mod;b>>=1;}return ct;}
bool Miller_Rabin(ll x){
if(x<2) return 0;
if(x==2||x==3) return 1;
ll b=x-1,ct=0;
while(!(b&1)) b>>=1,ct++;
for(int i=0;i<10;i++){
ll a=rand()%(x-2)+2,p=qp(a,b,x);
if(p==1||p==x-1) continue;
for(int j=1;j<ct;j++){
p=(__int128)p*p%x;
if(p==x-1) break;
}
if(p!=x-1) return 0;
}
return 1;
}
ll Pollard_Rho(ll x){
ll c=rand()%(x-1)+1;
for(ll ct=1,s=0,t=0,p=1;;ct*=2,s=t,p=1){
for(ll i=1;i<=ct;i++){
t=((__int128)t*t+c)%x;
p=(__int128)p*abs(t-s)%x;
if(!(i%127)){
ll tmp=__gcd(p,x);
if(tmp>1) return tmp;
}
}
ll tmp=gcd(p,x);
if(tmp>1) return tmp;
}
}
void fac(ll x){
if(x<=mx||x<2) return;
if(Miller_Rabin(x)){mx=max(mx,x);return;}
ll ct=x;
while(ct>=x) ct=Pollard_Rho(x);
while(!(x%ct)) x/=ct;
fac(x),fac(ct);
}
线性代数
矩阵快速幂
struct MAT{
ll a[3][3]={};
ll* operator[](int x){return a[x];}
MAT operator*(MAT& b){
MAT res;
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
for(int k=1;k<=2;k++)
(res[i][j]+=a[i][k]*b[k][j])%=mod;
return res;
}
}a,ans;
void qp(ll b){while(b){if(b&1) ans=ans*a;a=a*a,b>>=1;}}
void init(){a[1][1]=a[1][2]=a[2][1]=ans[1][1]=ans[2][2]=1;}
ll get_ans(ll n){qp(n);return ans[1][2];}
高斯消元
bool solve(){
for(int i=1;i<=n;i++){
ll r=i;
for(int j=i+1;j<=n;j++)
if(fabs(a[j][i])>fabs(a[r][i])) r=j;
if(fabs(a[r][i])<eps) return 1;
if(r!=i) swap(a[i],a[r]);
double t=a[i][i];
for(int j=i;j<=n+1;j++) a[i][j]/=t;
for(int j=i+1;j<=n;j++){
t=a[j][i];
for(int k=i;k<=n+1;k++)
a[j][k]-=a[i][k]*t;
}
}
x[n]=a[n][n+1];
for(int i=n-1;i>=1;i--){
x[i]=a[i][n+1];
for(int j=i+1;j<=n;j++)
x[i]-=(a[i][j]*x[j]);
}
return 0;
}
矩阵求逆
void Gauss(){
for(int i=1,r;i<=n;i++){
r=i;
for(int j=i+1;j<=n;j++)
if(fabs(a[j][i])>fabs(a[r][i])) r=j;
if(r!=i) swap(a[r],a[i]);
if(!a[i][i]){cout<<"No Solution";return;}
ll t=qp(a[i][i],mod-2);
for(int j=1;j<=n;j++){
if(i==j) continue;
ll q=a[j][i]*t%mod;
for(int k=i;k<=(n<<1);k++)
a[j][k]-=a[i][k]*q,a[j][k]%=mod,a[j][k]+=mod,a[j][k]%=mod;
}
for(int j=1;j<=(n<<1);j++) a[i][j]*=t,a[i][j]%=mod;
}
for(int i=1;i<=n;i++)
for(int j=n+1;j<=(n<<1);j++)
cout<<a[i][j]<<(j==(n<<1)?"\n":" ");
}
void init(){for(int i=1;i<=n;i++) a[i][n+1]=1;}
行列式求值
ll solve(){
ll res=1,kk=1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
while(a[i][i]){
ll t=a[j][i]/a[i][i];
for(int k=i;k<=n;k++) ((a[j][k]-=a[i][k]*t)+=mod)%=mod;
swap(a[i],a[j]),kk=-kk;
}
swap(a[i],a[j]),kk=-kk;
}
for(int i=1;i<=n;i++) res*=a[i][i],res%=mod;
res*=kk,res%=mod,res+=mod,res%=mod;
return res;
}
数据结构
线段树家族
线段树 1
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=min(t[ls],t[rs]);}
void down(ll rt,ll k){t[rt]+=k,lazy[rt]+=k;}
void push_down(ll rt){if(lazy[rt]) down(ls,lazy[rt]),down(rs,lazy[rt]),lazy[rt]=0;}
void build(ll rt,ll l,ll r){if(l==r){t[rt]=a[l];return;}build(L),build(R),up(rt);}
void add(ll rt,ll l,ll r,ll rl,ll rr,ll k){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){down(rt,k);return;}
push_down(rt),add(L,rl,rr,k),add(R,rl,rr,k),up(rt);
}
ll query(ll rt,ll l,ll r,ll rl,ll rr){
if(rl>r||rr<l) return 1e18;
if(rl<=l&&r<=rr) return t[rt];
push_down(rt);return min(query(L,rl,rr),query(R,rl,rr));
}
线段树 2
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=(t[ls]+t[rs])%mod;}
void build(ll rt,ll l,ll r){
lazy2[rt]=1;if(l==r){t[rt]=a[l];return;}
build(L),build(R);up(rt);
}
void down(ll rt,ll l,ll r,ll k,ll k2){
(t[rt]*=k2)%=mod,(t[rt]+=k*(r-l+1)%mod)%=mod;
(lazy[rt]*=k2)%=mod,(lazy[rt]+=k)%=mod,(lazy2[rt]*=k2)%=mod;
}
void push_down(ll rt,ll l,ll r){down(L,lazy[rt],lazy2[rt]),down(R,lazy[rt],lazy2[rt]),lazy[rt]=0,lazy2[rt]=1;}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll k){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){(t[rt]+=(r-l+1)*k)%=mod,(lazy[rt]+=k)%=mod;return;}
push_down(rt,l,r);update(L,rl,rr,k),update(R,rl,rr,k);up(rt);
}
void update2(ll rt,ll l,ll r,ll rl,ll rr,ll k){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){(t[rt]*=k)%=mod,(lazy[rt]*=k)%=mod,(lazy2[rt]*=k)%=mod;return;}
push_down(rt,l,r);update2(L,rl,rr,k),update2(R,rl,rr,k);up(rt);
}
ll query(ll rt,ll l,ll r,ll rl,ll rr){
if(rl>r||rr<l) return 0;
if(rl<=l&&r<=rr) return t[rt];
push_down(rt,l,r);return (query(L,rl,rr)+query(R,rl,rr))%mod;
}
动态开点线段树
#define mid (l+r>>1)
#define L t[rt].ls,l,mid
#define R t[rt].rs,mid+1,r
struct Tree{ll ls,rs,val;}t[N];
void up(ll rt){t[rt].val=t[t[rt].ls].val+t[t[rt].rs].val;}
void down(ll rt,ll l,ll r,ll k){lazy[rt]=k,t[rt].val=(r-l+1)*k;}
void push_down(ll rt,ll l,ll r){if(~lazy[rt]) down(L,lazy[rt]),down(R,lazy[rt]),lazy[rt]=-1;}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll k){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){down(rt,l,r,k);return;}
if(!t[rt].ls) t[rt].ls=++ct;if(!t[rt].rs) t[rt].rs=++ct;
push_down(rt,l,r);
update(L,rl,rr,k);update(R,rl,rr,k);up(rt);
}
线段树-区间加 区间求 gcd
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=__gcd(t[ls],t[rs]),s[rt]=s[ls]+s[rs];}
void build(ll rt,ll l,ll r){
if(l==r){t[rt]=s[rt]=a[l]-a[l-1];return;}
build(L),build(R),up(rt);
}
void update(ll rt,ll l,ll r,ll x,ll d){
if(l>x||r<x) return;
if(l==r){t[rt]+=d,s[rt]+=d;return;}
update(L,x,d),update(R,x,d),up(rt);
}
ll query(ll rt,ll l,ll r,ll rl,ll rr){
if(rl>r||rr<l) return 0;
if(rl<=l&&r<=rr) return t[rt];
return __gcd(query(L,rl,rr),query(R,r,rl,rr));
}
ll sum(ll rt,ll l,ll r,ll rl,ll rr){
if(rl>r||rr<l) return 0;
if(rl<=l&&r<=rr) return s[rt];
return sum(L,rl,rr)+sum(R,rl,rr);
}
void upd(ll l,ll r,ll d){update(1,1,n,l,d),update(1,1,n,r+1,-d);}
ll qry(ll l,ll r){return abs(__gcd(query(1,1,n,l+1,r),sum(1,1,n,1,l)));}
线段树-区间赋值 区间覆盖 区间求和
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=t[ls]+t[rs];}
void push_down(ll rt,ll l,ll r){
if(~lazy2[rt]){
t[ls]=lazy2[rt]*(mid-l+1);
t[rs]=lazy2[rt]*(r-mid);
lazy2[ls]=lazy2[rs]=lazy2[rt];
lazy[ls]=lazy[rs]=0,lazy2[rt]=-1;
}
if(lazy[rt]){
lazy[ls]^=1,lazy[rs]^=1;
t[ls]=mid-l+1-t[ls],t[rs]=r-mid-t[rs];
lazy[rt]=0;
}
}
void update(ll rt,ll l,ll r,ll rl,ll rr){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){lazy[rt]^=1;t[rt]=r-l+1-t[rt];return;}
push_down(rt,l,r);update(L,rl,rr),update(R,r,rl,rr);up(rt);
}
void cover(ll rt,ll l,ll r,ll rl,ll rr,ll k){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){t[rt]=(r-l+1)*k;lazy2[rt]=k,lazy[rt]=0;return;}
push_down(rt,l,r);cover(L,rl,rr,k),cover(R,rl,rr,k);up(rt);
}
ll query(ll rt,ll l,ll r){
if(l==r) return l;
push_down(rt,l,r);
if(t[rt<<1]<mid-l+1) return query(L);
return query(R);
}
void init(){memset(lazy2,-1,sizeof lazy2);}
线段树分治
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void init(){for(int i=1;i<=n*2;i++) fa[i]=i,sz[i]=1;}
ll getfa(ll x){return fa[x]==x?x:getfa(fa[x]);}
void hb(ll x,ll y){
ll fx=getfa(x),fy=getfa(y);
if(fx==fy) return;
if(sz[fx]>sz[fy]) fx^=fy^=fx^=fy;
s.push({fx,sz[fx]==sz[fy]});fa[fx]=fy,sz[fy]+=(sz[fx]==sz[fy]);
}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll k){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){t[rt].push_back(k);return;}
update(L,rl,rr,k),update(R,rl,rr,k);
}
void dfs(ll rt,ll l,ll r){
bool flag=1;ll lst=s.size();
for(auto i:t[rt]){
ll fx=getfa(x[i]),fy=getfa(y[i]);
if(fx==fy){
for(int i=l;i<=r;i++) cout<<"No\n";
flag=0;
break;
}
hb(x[i],y[i]+n),hb(y[i],x[i]+n);
}
if(flag){
if(l==r) cout<<"Yes\n";
else dfs(L),dfs(R);
}
while(s.size()>lst) sz[fa[s.top().fi]]-=s.top().se,fa[s.top().fi]=s.top().fi,s.pop();
}
线段树优化建图
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void Add(ll x,ll y,ll w=0){e[x].pb(y,(~w?w:0));if(!~w) Add(y,x);}
void build(ll rt,ll l,ll r){
if(l==r){leaf[l]=rt;return;}
Add(rt,ls),Add(rt,rs);
Add(ls+P,rt+P),Add(rs+P,rt+P);
build(L),build(R);
}
void add(ll rt,ll l,ll r,ll rl,ll rr,ll v,ll w,ll op){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){
if(op) Add(rt+P,v,w);
else Add(v,rt,w);
return;
}
add(L,rl,rr,v,w,op),add(R,rl,rr,v,w,op);
}
void dijkstra(){
priority_queue<pii,vector<pii>,greater<pii> > q;
memset(dis,0x3f,sizeof dis);
q.push({dis[leaf[s]+P]=0,leaf[s]+P});
while(!q.empty()){
ll x=q.top().se;q.pop();
if(vis[x]) continue;
vis[x]=1;
for(auto p:e[x]){
ll y=p.fi,w=p.se;
if(dis[y]>dis[x]+w) q.push({dis[y]=dis[x]+w,y});
}
}
}
void solve(){
cin>>n>>q>>s;build(1,1,n);
while(q--){
cin>>op>>v;
if(op==1) cin>>u>>w,Add(leaf[v],leaf[u],w);
else cin>>l>>r>>w,add(1,1,n,l,r,leaf[v],w,op&1);
}
for(int i=1;i<=n;i++) Add(leaf[i],leaf[i]+P,-1);
dijkstra();
for(int i=1;i<=n;i++) cout<<(dis[leaf[i]]==inf?-1:dis[leaf[i]])<<" ";
}
扫描线
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid,r
// 上一行注意!
struct P{ll h,x,y,op;bool operator<(const P& b){return h==b.h?x>b.x:h<b.h;}}p[N];
struct Q{ll s,l;}tree[N];// 开大一点!!!
void up(ll rt,ll l,ll r){
if(tree[rt].s>0) tree[rt].l=y[r]-y[l];
else tree[rt].l=tree[ls].l+tree[rs].l;
}
void change(ll rt,ll l,ll r,ll rl,ll rr,ll k){
if(rl>=y[r]||y[l]>=rr) return;
if(rl<=y[l]&&y[r]<=rr){tree[rt].s+=k,up(rt,l,r);return;}
change(L,rl,rr,k),change(R,rl,rr,k),up(rt,l,r);
}
void solve(){
cin>>n;n<<=1;
for(int i=1;i<n;i+=2){
cin>>sx>>sy>>ex>>ey;
p[i]={sx,sy,ey,1},p[i+1]={ex,sy,ey,-1};
y[i]=sy,y[i+1]=ey;
}
sort(y+1,y+n+1),sort(p+1,p+n+1);
for(int i=1;i<=n;i++)
if(y[i]!=y[i+1]) y[++ct]=y[i];
for(int i=1;i<n;i++)
change(1,1,ct,p[i].x,p[i].y,p[i].op),ans+=(p[i+1].h-p[i].h)*tree[1].l;
cout<<ans;
}
树状数组 1
#define lowbit(x) (x)&(-(x))
void xg(ll x,ll k){while(x<=n) s[x]+=k,x+=lowbit(x);}
ll sum(ll x,ll ct=0){while(x) ct+=s[x],x-=lowbit(x);return ct;}
ll getsum(ll l,ll r){return sum(r)-sum(l-1);}
树状数组 2
void xg(ll s[],ll x,ll k){while(x<=n) s[x]+=k,x+=lowbit(x);}
void qxg(ll x,ll y,ll k){xg(s,x,k);xg(s,y+1,-k);xg(s2,x,x*k);xg(s2,y+1,-(y+1)*k);}
ll sum(ll s[],ll x,ll ct=0){while(x) ct+=s[x],x-=lowbit(x);return ct;}
ll getsum(ll l,ll r){return (r+1)*sum(s,r)-sum(s2,r)-l*sum(s,l-1)+sum(s2,l-1);}
Treap
#define ls t[rt].son[0]
#define rs t[rt].son[1]
struct T{ll val,data,sz,cnt,son[2];}t[N];
ll New(ll x){t[++ct].val=x,t[ct].data=rand(),t[ct].sz=t[ct].cnt=1;return ct;}
void up(ll rt){t[rt].sz=t[ls].sz+t[rs].sz+t[rt].cnt;}
void rot(ll &rt,bool d){
int p=t[rt].son[!d];t[rt].son[!d]=t[p].son[d],t[p].son[d]=rt,rt=p;
up(t[rt].son[d]),up(rt);
}
void insert(ll &rt,ll x){
if(!rt){rt=New(x);return;}
if(t[rt].val==x){t[rt].cnt++,up(rt);return;}
bool d=(x>t[rt].val);insert(t[rt].son[d],x);
if(t[rt].data<t[t[rt].son[d]].data) rot(rt,!d);
up(rt);
}
void del(ll &rt,ll x){
if(!rt) return;
if(t[rt].val==x){
if(t[rt].cnt>1){t[rt].cnt--;up(rt);return;}
if(ls||rs){
if(!rs||t[ls].data>t[rs].data) rot(rt,1),del(rs,x);
else rot(rt,0),del(ls,x);
up(rt);
}else rt=0;
return;
}
if(x<t[rt].val) del(ls,x);
else del(rs,x);
up(rt);
}
ll rnk(ll rt,ll x){
if(!rt) return 1;
if(t[rt].val==x) return t[ls].sz+1;
if(t[rt].val>x) return rnk(ls,x);
return t[ls].sz+t[rt].cnt+rnk(rs,x);
}
ll search(ll rt,ll x){
if(!rt) return inf;
if(x<=t[ls].sz) return search(ls,x);
if(x<=t[ls].sz+t[rt].cnt) return t[rt].val;
return search(rs,x-t[ls].sz-t[rt].cnt);
}
ll pre(ll x){
ll rt=root,p=0;
while(rt)
if(t[rt].val<x) p=t[rt].val,rt=rs;
else rt=ls;
return p;
}
ll nxt(ll x){
ll rt=root,p=0;
while(rt)
if(t[rt].val>x) p=t[rt].val,rt=ls;
else rt=rs;
return p;
}
splay
ll ct,rt;
struct T{ll sz,fa,key,son[2];}t[N];
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define son(x,p) t[x].son[p]
#define fa(x) t[x].fa
#define key(x) t[x].key
#define sz(x) t[x].sz
ll New(ll x){ct++,key(ct)=x,sz(ct)=1;return ct;}
void up(ll x){sz(x)=sz(ls(x))+sz(rs(x))+1;}
bool getd(ll x,ll y){return x==rs(y);}
void clr(ll x){ls(x)=rs(x)=fa(x)=key(x)=sz(x)=0;}
void rot(ll x){
ll y=fa(x),z=fa(y);bool d=getd(x,fa(x));
if(son(x,d^1)) fa(son(x,d^1))=y;
son(y,d)=son(x,d^1),son(x,d^1)=y;fa(x)=z,fa(y)=x;
if(z) son(z,getd(y,z))=x;
up(y),up(x);
}
void splay(ll x){
for(int i;i=fa(x);rot(x))
if(fa(i)) rot(getd(x,fa(x))==getd(i,fa(i))?i:x);
rt=x;
}
void insert(ll x){
ll y=rt,lst=0;
while(y) lst=y,y=son(y,x>key(y));
y=New(x),fa(y)=lst,son(lst,x>key(lst))=y;
splay(y);
}
void del(ll x){
ll y=rt,lst=0,p;
while(y&&key(y)!=x) lst=y,y=son(y,x>key(y));
if(!y){splay(lst);return;}
splay(y);p=ls(y);
if(!p){fa(rt=rs(y))=0,clr(y);return;}
while(rs(p)) p=rs(p);
rs(p)=rs(y),fa(rs(y))=p,fa(ls(y))=0;clr(y);
up(p),splay(p);
}
ll rk(ll x,ll res=1){
ll y=rt,lst=0;
while(y) lst=y,res+=(x>key(y))*(sz(ls(y))+1),y=son(y,x>key(y));
splay(lst);return res;
}
ll kth(ll x){
ll y=rt;
while(y)
if(sz(ls(y))+1<x) x-=sz(ls(y))+1,y=rs(y);
else if(sz(ls(y))+1==x) break;
else y=ls(y);
splay(y);return key(y);
}
ll pre(ll x){
ll y=rt,lst=0,p=0;
while(y){
lst=y;
if(x>key(y)) p=key(y);
y=son(y,x>key(y));
}
splay(lst);return p;
}
ll nxt(ll x){
ll y=rt,lst=0,p=0;
while(y){
lst=y;
if(x<key(y)) p=key(y);
y=son(y,x>=key(y));
}
splay(lst);return p;
}
主席树
#define mid (l+r>>1)
ll n,m,p,l,r,k,ct,a[N],b[N],rt[N];
struct T{ll ls,rs,val;}t[N<<5];
ll build(ll l,ll r){
ll rt=++ct;if(l==r) return rt;
t[rt].ls=build(l,mid),t[rt].rs=build(mid+1,r);
return rt;
}
ll mk(ll x){t[++ct]=t[x];return ct;}
ll update(ll rt,ll l,ll r,ll x){
if(l>x||r<x) return rt;
rt=mk(rt),t[rt].val++;
if(l==r) return rt;
t[rt].ls=update(t[rt].ls,l,mid,x),t[rt].rs=update(t[rt].rs,mid+1,r,x);
return rt;
}
ll query(ll rt,ll rt2,ll l,ll r,ll x){
if(l==r) return l;
ll tmp=t[t[rt2].ls].val-t[t[rt].ls].val;
if(x<=tmp) return query(t[rt].ls,t[rt2].ls,l,mid,x);
return query(t[rt].rs,t[rt2].rs,mid+1,r,x-tmp);
}
void init(){
for(int i=1;i<=n;i++) b[i]=a[i];
sort(b+1,b+n+1);p=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+p+1,a[i])-b;
rt[0]=build(1,p);for(int i=1;i<=n;i++) rt[i]=update(rt[i-1],1,p,a[i]);
}
ll qry(ll l,ll r){return b[query(rt[l-1],rt[r],1,p,k)];}
李超线段树
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
bool check(pii a,pii b){
if(abs(a.fi-b.fi)>eps) return a.fi-b.fi>eps;
return a.se>b.se;
}
db calc(ll i,ll x){return k[i]*x+b[i];}
void upd(ll rt,ll l,ll r,ll i){
if(check({calc(i,mid),t[rt]},{calc(t[rt],mid),i})) swap(i,t[rt]);
if(check({calc(i,l),t[rt]},{calc(t[rt],l),i})) upd(L,i);
if(check({calc(i,r),t[rt]},{calc(t[rt],r),i})) upd(R,i);
}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll i){
if(rl>r||rr<l) return;
if(rl<=l&&r<=rr){upd(rt,l,r,i);return;}
update(L,rl,rr,i),update(R,rl,rr,i);
}
pii query(ll rt,ll l,ll r,ll x){
if(l>x||r<x) return {0,-m2};
if(l==r) return {calc(t[rt],x),-t[rt]};
return max({{calc(t[rt],x),-t[rt]},query(L,x),query(R,x)});
}
lct
ll n,m,op,x,y;
struct T{ll sz,fa,key,tag,son[2];}t[N];
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define son(x,p) t[x].son[p]
#define fa(x) t[x].fa
#define key(x) t[x].key
#define sz(x) t[x].sz
#define tag(x) t[x].tag
void up(ll x){sz(x)=sz(ls(x))^sz(rs(x))^key(x);}
bool getd(ll x){return x==rs(fa(x));}
bool isrt(ll x){return ls(fa(x))!=x&&rs(fa(x))!=x;}
void push_down(ll x){if(tag(x)) swap(ls(x),rs(x)),tag(ls(x))^=1,tag(rs(x))^=1,tag(x)=0;}
void update(ll x){if(!isrt(x)) update(fa(x));push_down(x);}
void rot(ll x){
ll y=fa(x),z=fa(y);bool d=getd(x);
if(!isrt(y)) son(z,getd(y))=x;
fa(son(x,d^1))=y;son(y,d)=son(x,d^1),son(x,d^1)=y;fa(x)=z,fa(y)=x;
up(y),up(x);
}
void splay(ll x){
update(x);
for(int i;i=fa(x),!isrt(x);rot(x))
if(!isrt(i)) rot(getd(x)==getd(i)?i:x);
}
void access(ll x,ll lst=0){
while(x){
splay(x),rs(x)=lst;
lst=x;up(x);x=fa(x);
}
}
void mkrt(ll x){access(x),splay(x),tag(x)^=1;}
ll fd(ll x){
access(x),splay(x),push_down(x);
while(ls(x)) x=ls(x),push_down(x);
splay(x);return x;
}
void split(ll x,ll y){mkrt(x),access(y),splay(y);}
void link(ll x,ll y){mkrt(x);if(fd(y)!=x) fa(x)=y;}
void cut(ll x,ll y){mkrt(x);if(fd(y)==x&&fa(y)==x&&!ls(y)) fa(y)=rs(x)=0;}
暴力数据结构
带修莫队
struct Q{
ll x,y,i,pos,posy,t;
bool operator<(const Q& B){return pos!=B.pos?pos<B.pos:(posy!=B.posy?posy<B.posy:t<B.t);}
}q[N],g[N];
void add(ll x){res+=!cnt[x]++;}
void del(ll x){res-=!--cnt[x];}
void Mo(ll x,ll y){
while(l>x) add(a[--l]);
while(r<y) add(a[++r]);
while(l<x) del(a[l++]);
while(r>y) del(a[r--]);
}
void up(ll x,ll y,ll t){
if(x<=g[t].x&&g[t].x<=y) del(a[g[t].x]),add(g[t].y);
swap(a[g[t].x],g[t].y);
}
void xg(ll k,ll x,ll y){
while(t<k) up(x,y,++t);
while(t>k) up(x,y,t--);
}
回滚莫队
ll n,m,S,tot,res,a[N],t[N],ans[N],l,r,L[N],R[N],tl[N],tr[N];
bool vis[N];
struct Q{ll x,y,i,pos;bool operator<(const Q& B){return pos!=B.pos?pos<B.pos:y<B.y;}}q[N];
void add(ll x){L[a[x]]=min(L[a[x]],x),R[a[x]]=max(R[a[x]],x),res=max(res,R[a[x]]-L[a[x]]);}
void solve(){
cin>>n;S=sqrt(n);
for(int i=1;i<=n;i++) cin>>a[i],t[++tot]=a[i];
sort(t+1,t+tot+1);tot=unique(t+1,t+tot+1)-t-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(t+1,t+tot+1,a[i])-t;
cin>>m;for(int i=1;i<=m;i++) cin>>l>>r,q[i]={l,r,i,(l-1)/S+1};
sort(q+1,q+m+1);memset(tl,0x3f,sizeof tl);
for(int i=1,j=1;i<=(n-1)/S+1&&j<=m;i++){
r=min(i*S,n),res=0;
memset(L,0x3f,sizeof L);
memset(R,0,sizeof R);
while(q[j].pos==i){
l=min(i*S,n)+1;
if(q[j].y-q[j].x<=S){
for(ll k=q[j].x;k<=q[j].y;k++)
tl[a[k]]=min(tl[a[k]],k),tr[a[k]]=max(tr[a[k]],k),ans[q[j].i]=max(ans[q[j].i],tr[a[k]]-tl[a[k]]);
for(int k=q[j].x;k<=q[j].y;k++) tl[a[k]]=n,tr[a[k]]=0;
j++;continue;
}
while(r<q[j].y) add(++r);
ll tmp=res;
while(l>q[j].x){
--l;
if(!vis[a[l]]) vis[a[l]]=1,tl[a[l]]=L[a[l]],tr[a[l]]=R[a[l]];
add(l);
}
ans[q[j].i]=res,res=tmp;
while(l<=min(i*S,n)){if(vis[a[l]]) vis[a[l]]=0,L[a[l]]=tl[a[l]],R[a[l]]=tr[a[l]],tl[a[l]]=n,tr[a[l]]=0;l++;}
j++;
}
}
for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
}
其他
st 表
void init(){
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
}
ll query(ll l,ll r){
ll k=log2(r-l+1);
return max(st[l][k],st[r-(1<<k)+1][k]);
}
Trie
void insert(string s){
ll x=0;
for(auto c:s){
if(!trie[x][c]) trie[x][c]=++ct;
x=trie[x][c],tot[x]++;
}
}
ll query(string s){
ll x=0;
for(auto c:s){
if(!trie[x][c]) return 0;
x=trie[x][c];
}
return tot[x];
}
void init(){
for(int i=0;i<=ct;i++)
for(int j=0;j<128;j++) trie[i][j]=0;
for(int i=0;i<=ct;i++) tot[i]=0;
ct=0;
}
笛卡尔树
void build(){
s[1]=top=1;
for(int i=2;i<=n;i++){
while(top&&a[i]<a[s[top]]) top--;
if(!top) ls[i]=s[1];
else ls[i]=rs[s[top]],rs[s[top]]=i;
s[++top]=i;
}
}
整体二分
#define lowbit(x) (x&-x)
ll n,m,x,ans[N],t[N];
struct Q{ll l,r,k,i;}q[N];
struct A{ll x,i;}a[N];
void add(ll x,ll k){while(x<=n) t[x]+=k,x+=lowbit(x);}
ll query(ll x,ll ct=0){while(x) ct+=t[x],x-=lowbit(x);return ct;}
void solve(ll l,ll r,ll lq,ll la,Q q[],A a[]){
if(!lq) return;
if(l==r){for(int i=1;i<=lq;i++) ans[q[i].i]=l;return;}
Q q1[N],q2[N];A a1[N],a2[N];
ll mid=(l+r)>>1,lq1=0,lq2=0,la1=0,la2=0;
for(int i=1;i<=la;i++)
if(a[i].x<=mid) add(a[i].i,1),a1[++la1]=a[i];
else a2[++la2]=a[i];
for(int i=1;i<=lq;i++)
if(query(q[i].r)-query(q[i].l-1)>=q[i].k) q1[++lq1]=q[i];
else q[i].k-=query(q[i].r)-query(q[i].l-1),q2[++lq2]=q[i];
for(int i=1;i<=la1;i++) add(a1[i].i,-1);
solve(l,mid,lq1,la1,q1,a1);
solve(mid+1,r,lq2,la2,q2,a2);
}
图论/树论
tarjan 系列
缩点
void tarjan(ll x){
dfn[x]=low[x]=++ct;s.push(x),vis[x]=1;
for(auto y:e[x])
if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(vis[y]) low[x]=min(low[x],dfn[y]);
if(dfn[x]==low[x]){
tot++;
while(s.top()!=x) belong[s.top()]=tot,sz[tot]++,vis[s.top()]=0,s.pop();
s.pop(),vis[x]=0,belong[x]=tot,sz[tot]++;
}
}
割点
void tarjan(ll x,ll fa,ll rt,ll s=0){
dfn[x]=low[x]=++ct;
for(auto y:e[x]){
if(y==fa) continue;
if(!dfn[y]){
s++;tarjan(y,x,rt);low[x]=min(low[x],low[y]);
if(x!=rt&&low[y]>=dfn[x]) ans+=!ok[x],ok[x]=1;
}else if(dfn[y]<dfn[x]) low[x]=min(low[x],dfn[y]);
}
if(x==rt&&s>=2) ans+=!ok[x],ok[x]=1;
}
点双
void tarjan(ll x,ll fa,ll rt,ll son=0){
low[x]=dfn[x]=++ct;s[++top]=x;
for(auto y:e[x])
if(!dfn[y]){
son++,tarjan(y,x,rt),low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
ans++;
do{
p[ans].pb(s[top--]);
}while(s[top+1]!=y);
p[ans].pb(x);
}
}else if(dfn[y]<dfn[x]&&y!=fa) low[x]=min(low[x],dfn[y]);
if(x==rt&&!son) p[++ans].pb(x);
}
边双
void tarjan(ll x,ll fa){
dfn[x]=low[x]=++ct,s[++top]=x;
for(int i=h[x];i;i=nxt[i]){
if((~fa)&&i==(fa^1)) continue;
if(!dfn[to[i]]) tarjan(to[i],i),low[x]=min(low[x],low[to[i]]);
else low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x]){
tot++;
while(s[top+1]!=x) p[tot].push_back(s[top--]);
}
}
网络流
网络最大流
ll n,m,S,T,u,v,w,ct=1,ans,h[N],d[N],now[N];
struct P{ll to,nxt,w;}e[N];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
memset(d,-1,sizeof d);
queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
while(!q.empty()){
ll x=q.front();q.pop();
for(int i=h[x];i;i=e[i].nxt)
if(e[i].w&&!~d[e[i].to]){
d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
if(e[i].to==T) return 1;
}
}
return 0;
}
ll dfs(ll x,ll f,ll res=0){
if(x==T) return f;
for(int i=now[x];i&&f;i=e[i].nxt){
now[x]=i;
if(e[i].w&&d[e[i].to]==d[x]+1){
ll t=dfs(e[i].to,min(f,e[i].w));
if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
else d[e[i].to]=-1;
}
}
return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
最小费用最大流
ll n,S,T,ct=1,mincost,h[N],d[N],now[N];
bool vis[N];
struct P{ll to,nxt,w,c;}e[N];
void add(ll x,ll y,ll w,ll c,bool p=1){e[++ct]={y,h[x],w,c},h[x]=ct;if(p) add(y,x,0,-c,0);}
bool spfa(){
queue<ll> q;q.push(S);
for(int i=0;i<=T;i++) d[i]=1e9,vis[i]=0,now[i]=h[i];d[S]=0,vis[S]=1;
while(q.size()){
ll x=q.front();q.pop();vis[x]=0;
for(int i=h[x];i;i=e[i].nxt)
if(d[e[i].to]>d[x]+e[i].c&&e[i].w){
d[e[i].to]=d[x]+e[i].c;
if(!vis[e[i].to]) q.push(e[i].to),vis[e[i].to]=1;
}
}
return d[T]!=1e9;
}
ll dfs(ll x,ll f,ll ct=0){
if(x==T) return f;
vis[x]=1;
for(int i=now[x];i&&f;i=e[i].nxt){
now[x]=i;
if(!vis[e[i].to]&&e[i].w&&d[e[i].to]==d[x]+e[i].c){
ll t=dfs(e[i].to,min(f,e[i].w));
if(!t) d[e[i].to]=1e9;
else e[i].w-=t,e[i^1].w+=t,f-=t,ct+=t,mincost+=t*e[i].c;
}
}
vis[x]=0;
return ct;
}
ll dinic(){while(spfa()) dfs(S,1e9);return mincost;}
无源汇有上下界可行流
ll n,m,x,y,wl,wr,ct=1,tot,S,T,h[N],a[N],l[M],now[N],d[N];
struct P{ll to,nxt,w;}e[M];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
memset(d,-1,sizeof d);
queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
while(!q.empty()){
ll x=q.front();q.pop();
for(int i=h[x];i;i=e[i].nxt)
if(e[i].w&&!~d[e[i].to]){
d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
if(e[i].to==T) return 1;
}
}
return 0;
}
ll dfs(ll x,ll f,ll res=0){
if(x==T) return f;
for(int i=now[x];i&&f;i=e[i].nxt){
now[x]=i;
if(e[i].w&&d[e[i].to]==d[x]+1){
ll t=dfs(e[i].to,min(f,e[i].w));
if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
else d[e[i].to]=-1;
}
}
return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
void solve(){
cin>>n>>m;T=n+1;
for(int i=1;i<=m;i++) cin>>x>>y>>wl>>wr,add(x,y,wr-wl),l[ct]=wl,a[x]-=wl,a[y]+=wl;
for(int i=1;i<=n;i++)
if(a[i]>0) add(S,i,a[i]),tot+=a[i];
else add(i,T,-a[i]);
if(dinic()!=tot) cout<<"NO";
else{
cout<<"YES\n";
for(int i=2;i<m*2+2;i+=2) cout<<l[i^1]+e[i^1].w<<"\n";
}
}
有源汇有上下界最大流
ll n,m,x,y,wl,wr,ct=1,tot,S,T,SS,TT,h[N],a[N],now[N],d[N];
struct P{ll to,nxt,w;}e[M];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
memset(d,-1,sizeof d);
queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
while(!q.empty()){
ll x=q.front();q.pop();
for(int i=h[x];i;i=e[i].nxt)
if(e[i].w&&!~d[e[i].to]){
d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
if(e[i].to==T) return 1;
}
}
return 0;
}
ll dfs(ll x,ll f,ll res=0){
if(x==T) return f;
for(int i=now[x];i&&f;i=e[i].nxt){
now[x]=i;
if(e[i].w&&d[e[i].to]==d[x]+1){
ll t=dfs(e[i].to,min(f,e[i].w));
if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
else d[e[i].to]=-1;
}
}
return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
void solve(){
cin>>n>>m>>SS>>TT;S=n+2,T=n+3;
for(int i=1;i<=m;i++) cin>>x>>y>>wl>>wr,add(x,y,wr-wl),a[x]-=wl,a[y]+=wl;
for(int i=0;i<=n+1;i++)
if(a[i]>0) add(S,i,a[i]),tot+=a[i];
else add(i,T,-a[i]);
add(TT,SS,inf);
if(dinic()!=tot) cout<<"please go home to sleep";
else{
ll ans=e[ct].w;e[ct^1].w=e[ct].w=0;
S=SS,T=TT;cout<<ans+dinic();
}
}
有源汇有上下界最小流
ll n,m,x,y,wl,wr,ct=1,tot,S,T,SS,TT,h[N],a[N],now[N],d[N];
struct P{ll to,nxt,w;}e[M];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
memset(d,-1,sizeof d);
queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
while(!q.empty()){
ll x=q.front();q.pop();
for(int i=h[x];i;i=e[i].nxt)
if(e[i].w&&!~d[e[i].to]){
d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
if(e[i].to==T) return 1;
}
}
return 0;
}
ll dfs(ll x,ll f,ll res=0){
if(x==T) return f;
for(int i=now[x];i&&f;i=e[i].nxt){
now[x]=i;
if(e[i].w&&d[e[i].to]==d[x]+1){
ll t=dfs(e[i].to,min(f,e[i].w));
if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
else d[e[i].to]=-1;
}
}
return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
void solve(){
cin>>n>>m>>SS>>TT;S=n+2,T=n+3;
for(int i=1;i<=m;i++) cin>>x>>y>>wl>>wr,add(x,y,wr-wl),a[x]-=wl,a[y]+=wl;
for(int i=0;i<=n+1;i++)
if(a[i]>0) add(S,i,a[i]),tot+=a[i];
else add(i,T,-a[i]);
add(TT,SS,inf);
if(dinic()!=tot) cout<<"please go home to sleep";
else{
ll ans=e[ct].w;e[ct^1].w=e[ct].w=0;
T=SS,S=TT;cout<<ans-dinic();
}
}
其他
dijkstra
void dijkstra(ll s){
priority_queue<pii,vector<pii>,greater<pii> > q;
memset(dis,0x3f,sizeof dis);q.push({dis[s]=0,s});
while(!q.empty()){
ll x=q.top().se;q.pop();
if(vis[x]) continue;vis[x]=1;
for(auto p:e[x]){
ll y=p.fi,w=p.se;
if(dis[y]>dis[x]+w) q.push({dis[y]=dis[x]+w,y});
}
}
}
kruskal
struct P{ll x,y,w;bool operator<(const P& B){return w<B.w;}}e[N];
ll getfa(ll x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
bool hb(ll x,ll y){x=getfa(x),y=getfa(y);if(x!=y){fa[x]=y;return 1;}return 0;}
void kruskal(){
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++) if(hb(e[i].x,e[i].y)) ans+=e[i].w;
}
lca
void dfs(ll x,ll fa){
d[x]=d[fa]+1,f[x][0]=fa;
for(int i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1];
for(auto y:e[x]) if(y!=fa) dfs(y,x);
}
ll lca(ll x,ll y){
if(d[x]<d[y]) swap(x,y);
for(int i=20;~i;i--) if(d[f[x][i]]>=d[y]) x=f[x][i];
if(x==y) return x;
for(int i=20;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
lca(树剖版)
void dfs(ll x){
sz[x]=1,d[x]=d[f[x]]+1;
for(auto y:e[x]) if(y!=f[x]) f[y]=x,dfs(y),sz[x]+=sz[y];
}
void dfs1(ll x){
ll t=0;
if(!top[x]) top[x]=x;
for(auto y:e[x]) if(y!=f[x]&&sz[y]>sz[t]) t=y;
if(t) top[t]=top[x],dfs1(t);
for(auto y:e[x]) if(y!=f[x]&&t!=y) dfs1(y);
}
ll lca(ll x,ll y){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) x^=y^=x^=y;
x=f[top[x]];
}
if(d[x]>d[y]) x^=y^=x^=y;
return x;
}
树剖(树状数组)
void xg(ll s[],ll x,ll k){while(x<=n) s[x]+=k,s[x]%=p,x+=lowbit(x);}
void qxg(ll x,ll y,ll k){
xg(s,x,k);xg(s,y+1,-k);
xg(s2,x,x*k);xg(s2,y+1,-(y+1)*k);
}
ll sum(ll s[],ll x){
ll ct=0;
while(x) ct+=s[x],ct%=p,x-=lowbit(x);
return ct;
}
ll query(ll l,ll r){return (((r+1)*sum(s,r)%p-sum(s2,r)-l*sum(s,l-1)%p+sum(s2,l-1))%p+p)%p;}
void add(ll x,ll y){e[x].pb(y),e[y].pb(x);}
void dfs(ll x,ll f){
fa[x]=f,sz[x]=1,d[x]=d[f]+1;
for(auto y:e[x]) if(y!=f) dfs(y,x),sz[x]+=sz[y],son[x]=(sz[y]>sz[son[x]]?y:son[x]);
}
void dfs2(ll x,ll f){
top[x]=f,id[x]=++ct;
if(w[x]) qxg(id[x],id[x],w[x]);
if(!son[x]) return;
dfs2(son[x],f);
for(auto y:e[x]) if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
void addp(ll x,ll y,ll k){
k%=p;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) x^=y^=x^=y;
qxg(id[top[x]],id[x],k),x=fa[top[x]];
}
if(d[x]>d[y]) x^=y^=x^=y;
qxg(id[x],id[y],k);
}
void adds(ll x,ll k){qxg(id[x],id[x]+sz[x]-1,k%p);}
ll queryp(ll x,ll y){
ll res=0;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) x^=y^=x^=y;
res+=query(id[top[x]],id[x]),res%=p,x=fa[top[x]];
}
if(d[x]>d[y]) x^=y^=x^=y;
res+=query(id[x],id[y]),res%=p;
return res;
}
ll querys(ll x){return query(id[x],id[x]+sz[x]-1);}
长链剖分
void dfs(ll x,ll fa){
d[x]=d[fa]+1;
for(auto y:e[x]) if(y!=fa) dfs(y,x);
rt=(d[rt]<d[x]?x:rt);
}
void dfs2(ll x,ll fa){
for(auto y:e[x]) if(y!=fa) dfs2(y,x),son[x]=(f[son[x]]>f[y]?son[x]:y);
f[x]=f[son[x]]+1;
for(auto y:e[x]) if(y!=fa&&y!=son[x]) chain.pb(f[y]);
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<n;i++) cin>>x>>y,e[x].pb(y),e[y].pb(x);
dfs(1,0);dfs2(rt,0),chain.pb(f[rt]);
sort(chain.begin(),chain.end(),greater<ll>());
for(int i=2;i<=n&&i-2<chain.size();i++) ans[i]=ans[i-1]+chain[i-2];
for(int i=chain.size()+2;i<=n;i++) ans[i]=ans[i-1];
ans[1]=1;
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}
Prüfer 序列
void prufer(){
ll x=0,leaf=0;
for(int i=1;i<=n;i++) if(!d[i]){x=leaf=i;break;}
for(int i=1;i<n-1;i++){
p[i]=fa[leaf];
if(!--d[fa[leaf]]&&fa[leaf]<x) leaf=fa[leaf];
else{while(d[++x]);leaf=x;}
}
}
void get_prufer(){
ll x=0,leaf=0;while(d[++x]);leaf=x;
for(int i=1;i<n-1;i++){
fa[leaf]=p[i];
if(!--d[fa[leaf]]&&fa[leaf]<x) leaf=fa[leaf];
else{while(d[++x]);leaf=x;}
}
fa[leaf]=n;
}
点分治
void getrt(ll x,ll fa,ll n){
sz[x]=1,mx[x]=0;
for(auto p:e[x]) if(p.fi!=fa&&!vis[p.fi]) getrt(p.fi,x,n),mx[x]=max(mx[x],sz[p.fi]),sz[x]+=sz[p.fi];
mx[x]=max(mx[x],n-sz[x]);
if(!rt||mx[x]<mx[rt]) rt=x;
}
void init(ll x,ll fa){
if(d[x]<M) t.pb(d[x]);
for(auto p:e[x]) if(p.fi!=fa&&!vis[p.fi]) d[p.fi]=d[x]+p.se,init(p.fi,x);
}
void calc(ll x){
all.clear();
for(auto p:e[x])
if(!vis[p.fi]){
t.clear(),d[p.fi]=p.se,init(p.fi,x);
for(int i=1;i<=m;i++) if(!ans[i]) for(auto l:t) if(q[i]>=l&&ok[q[i]-l]){ans[i]=1;break;}
for(auto l:t) ok[l]=1,all.pb(l);
}
for(auto l:all) ok[l]=0;
}
void solve(ll x){
vis[x]=ok[0]=1;calc(x);
for(auto p:e[x]) if(!vis[p.fi]) rt=0,getrt(p.fi,x,sz[p.fi]),solve(rt);
}
void treediv(){getrt(1,0,n);getrt(rt,0,n);solve(rt);}
LGV 引理
ll qp(ll a,ll b,ll ct=1){while(b){if(b&1) ct=ct*a%mod;a=a*a%mod,b>>=1;}return ct;}
ll C(ll n,ll m){return jc[n]*qp(jc[m],mod-2)%mod*qp(jc[n-m],mod-2)%mod;}
ll solve(ll n){
ll res=1,kk=1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
while(a[i][i]){
ll t=a[j][i]/a[i][i];
for(int k=i;k<=n;k++) ((a[j][k]-=a[i][k]*t)+=mod)%=mod;
swap(a[i],a[j]),kk=-kk;
}
swap(a[i],a[j]),kk=-kk;
}
for(int i=1;i<=n;i++) res*=a[i][i],res%=mod;
res*=kk,res%=mod,res+=mod,res%=mod;
return res;
}
void calc(){
cin>>n>>m;
for(int i=1;i<=m;i++) cin>>ta[i]>>tb[i];
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
if(ta[i]<=tb[j]) a[i][j]=C(tb[j]-ta[i]+n-1,n-1);
else a[i][j]=0;
cout<<solve(m)<<"\n";
}
计算几何
极角排序
#define double long double
const ll N=1e5+10;
const double pi=acos(-1);
ll n,ans1,ans2;
double ans;
struct P{
double x,y,a;ll i;
bool operator<(const P& b){return a<b.a;}
}p[N];
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y,p[i].i=i,p[i].a=atan2(p[i].y,p[i].x),p[i].a+=(p[i].a<0?pi*2.:0.);
sort(p+1,p+n+1);ans=p[1].a-p[n].a+pi*2.;ans1=p[1].i;ans2=p[n].i;
for(int i=2;i<=n;i++) if(p[i].a-p[i-1].a<ans) ans=p[i].a-p[i-1].a,ans2=p[i].i,ans1=p[i-1].i;
cout<<ans1<<" "<<ans2;
}
凸包
struct P{
double x,y;
bool operator<(const P& B)const{return x!=B.x?x<B.x:y<B.y;}
}a[N],s[N];
double K(P L,P R){return L.x!=R.x?(L.y-R.y)/(L.x-R.x):1e18;}
double dis(P L,P R){return sqrt((L.x-R.x)*(L.x-R.x)+(L.y-R.y)*(L.y-R.y));}
void solve(){
top=0;
for(int i=1;i<=n;i++){
s[++top]=a[i];
while(top>2&&K(s[top-2],s[top])<K(s[top-2],s[top-1])) s[top-1]=s[top],top--;
}
for(int i=1;i<top;i++) ans+=dis(s[i],s[i+1]);
}
void tubao(){
sort(a+1,a+n+1);solve();
reverse(a+1,a+n+1);solve();
}
半平面交
struct V{double x,y;}p[N],x[N];
struct P{V x,y;double an;}a[N],q[N];
P mk(V a,V b){return {a,b,atan2(b.y,b.x)};}
V operator +(V a,V b){return {a.x+b.x,a.y+b.y};}
V operator -(V a,V b){return {a.x-b.x,a.y-b.y};}
V operator *(V a,double b){return {a.x*b,a.y*b};}
V operator /(V a,double b){return {a.x/b,a.y/b};}
double dot(V a,V b){return a.x*b.x+a.y*b.y;}
double cross(V a,V b){return a.x*b.y-a.y*b.x;}
bool cmp(P a,P b){return a.an<b.an;}
bool check(P a,V b){return cross(a.y,b-a.x)<=-eps;}
V in(P a,P b){return a.x+a.y*(cross(b.y,a.x-b.x)/cross(a.y,b.y));}
bool half_plane(ll n){
sort(a+1,a+n+1,cmp);
q[0]=a[1];
for(int i=2;i<=n;i++){
while(l<r&&check(a[i],x[r])) r--;
while(l<r&&check(a[i],x[l+1])) l++;
q[++r]=a[i];
if(fabs(cross(q[r].y,q[r-1].y))<=eps){
if(check(q[r],q[r-1].x)&&dot(q[r].y,q[r-1].y)<=-eps) return 0;
r--;
if(!check(q[r],a[i].x)) q[r]=a[i];
}
if(l<r) x[r]=in(q[r],q[r-1]);
}
while(l<r&&check(q[l],x[r])) r--;
if(r-l<=1) return 0;
x[l]=in(q[l],q[r]);
return 1;
}
double polygonsize(ll n,V *a){
double res=0;
for(int i=1;i<n;i++) res+=cross(a[i],a[i+1]);
res+=cross(a[n],a[1]);
return res/2;
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>m;
for(int j=1;j<=m;j++) cin>>p[j].x>>p[j].y;
for(int j=1;j<m;j++) a[++ct]=mk(p[j],p[j+1]-p[j]);
a[++ct]=mk(p[m],p[1]-p[m]);
}
if(!half_plane(ct)) cout<<"0.000";
else cout<<fixed<<setprecision(3)<<polygonsize(r-l+1,x+l-1);
}
字符串
kmp
void init(){
for(int i=2,j=0;i<=m;i++){
while(j&&b[i]!=b[j+1]) j=nxt[j];
nxt[i]=(j+=(b[i]==b[j+1]));
}
}
void kmp(){
for(int i=1,j=0;i<=n;i++){
while(j&&a[i]!=b[j+1]) j=nxt[j];
if(a[i]==b[j+1]) j++;
if(j==m) cout<<i-m+1<<"\n",j=nxt[j];
}
}
exkmp
void Z(){
z[1]=m;
for(ll i=2,l=0,r=0;i<=m;i++){
if(i<=r) z[i]=min(z[i-l+1],r-i+1);
while(i+z[i]<=m&&t[i+z[i]]==t[1+z[i]]) z[i]++;
if(i+z[i]-1>r) l=i,r=i+z[i]-1;
}
}
void exkmp(){
Z();
for(ll i=1,l=0,r=0;i<=n;i++){
if(i<=r) p[i]=min(z[i-l+1],r-i+1);
while(i+p[i]<=n&&s[i+p[i]]==t[1+p[i]]) p[i]++;
if(i+p[i]-1>r) l=i,r=i+p[i]-1;
}
}
AC 自动机
ll n,ct,x,t[N][33],ed[N],fail[N],ans[N];
string s;vector<ll> e[N];
ll insert(string s,ll x=0){
for(auto c:s){
if(!t[x][c-'a']) t[x][c-'a']=++ct;
x=t[x][c-'a'];
}
return x;
}
void bfs(){
queue<ll> q;
for(int i=0;i<26;i++)
if(t[0][i]) q.push(t[0][i]);
while(q.size()){
ll x=q.front();q.pop();
for(int i=0;i<26;i++)
if(!t[x][i]) t[x][i]=t[fail[x]][i];
else fail[t[x][i]]=t[fail[x]][i],q.push(t[x][i]);
}
}
最小表示法
j=1;
for(;i<n&&j<n&&k<n;)
if(a[(i+k)%n]==a[(j+k)%n]) k++;
else if(a[(i+k)%n]>a[(j+k)%n]) i+=k+1,i+=(i==j),k=0;
else j+=k+1,i+=(i==j),k=0;
ans=min(i,j);
SA
void SA(){
for(int i=1;i<=n;i++) rk[i]=s[i],c[s[i]]++;
for(int i=2;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i;i--) sa[c[rk[i]]--]=i;
for(ll k=1;k<=n;k<<=1){
pos=0;for(int i=1;i<=m;i++) c[i]=0;
for(int i=n-k+1;i<=n;i++) rk2[++pos]=i;
for(int i=1;i<=n;i++) if(sa[i]>k) rk2[++pos]=sa[i]-k;
for(int i=1;i<=n;i++) c[rk[i]]++;
for(int i=2;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i;i--) sa[c[rk[rk2[i]]]--]=rk2[i],rk2[i]=0;
swap(rk,rk2);pos=1;rk[sa[1]]=1;
for(int i=2;i<=n;i++)
rk[sa[i]]=(pos+=(rk2[sa[i-1]]!=rk2[sa[i]]||rk2[sa[i-1]+k]!=rk2[sa[i]+k]));
if(pos==n) return;m=pos;
}
}
sam
int ct=1,lst=1,sum[N];ll ans;string s;
vector<int> e[N];
struct SAM{int fa=0,len=0,ch[26]={};}t[N];
void insert(int x){
int p=lst,np=lst=++ct;t[np].len=t[p].len+1;sum[ct]=1;
while(!t[p].ch[x]) t[p].ch[x]=np,p=t[p].fa;
if(!p) t[np].fa=1;
else{
int q=t[p].ch[x];
if(t[q].len==t[p].len+1) t[np].fa=q;
else{
int nq=++ct;t[nq]=t[q];t[nq].len=t[p].len+1,t[q].fa=t[np].fa=nq;
while(t[p].ch[x]==q) t[p].ch[x]=nq,p=t[p].fa;
}
}
}
void dfs(int x){
for(auto y:e[x]) dfs(y),sum[x]+=sum[y];
if(sum[x]!=1) ans=max(ans,1ll*sum[x]*t[x].len);
}
卡常
快读快写
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
火车头
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
以颤抖之身追赶,怀敬畏之心挑战。--《棋魂》

浙公网安备 33010602011771号