模板
缺省源
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
bool St;
struct IO
{
static const int Size=(1<<21);
char buf[Size],*p1,*p2;
int st[105],Top;
~IO(){clear();}
il void clear(){fwrite(buf,1,Top,stdout);Top=0;}
il char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,Size,stdin),p1==p2)?EOF:*p1++;}
il void pc(const char c){Top==Size&&(clear(),0);buf[Top++]=c;}
il IO& operator >>(char& c){while(c=gc(),c==' ' || c=='\n' || c=='\r');return *this;}
template<typename T>il IO& operator >>(T& x)
{
x=0;bool f=0;char c=gc();
while(!isdigit(c)){if(c=='-') f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
f?x=-x:0;
return *this;
}
il IO& operator >>(string& s)
{
s="";char c=gc();
while(c==' ' || c=='\n' || c=='\r') c=gc();
while(c!=' ' && c!='\n' && c!='\r' && c!=EOF) s+=c,c=gc();
return *this;
}
il IO& operator <<(const char c){pc(c);return *this;}
template<typename T> il IO& operator <<(T x)
{
if(x<0) pc('-'),x=-x;
do st[++st[0]]=x%10,x/=10;while(x);
while(st[0]) pc(st[st[0]--]+'0');
return *this;
}
il IO& operator <<(const string s){for(auto c:s) pc(c);return *this;}
il IO& operator <<(const char* c){for(int i=0;c[i];i++) pc(c[i]);return *this;}
} fin,fout;
bool Ed;
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// cerr<<(&St-&Ed)/1024.0/1024.0<<"Mib\n";
return 0;
}
数论
CRT
int a[11],b[11],n;
int mul(int x,int y,int mod)
{
int ret=0;
while(y)
{
if(y&1) ret=(ret+x)%mod;
x=(x+x)%mod;
y>>=1;
}
return ret;
}
int exgcd(int a,int b,int& x,int& y)
{
if(b==0)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}
int crt()
{
int M=1,ret=0;
for(int i=1;i<=n;i++) M*=a[i];
for(int i=1;i<=n;i++)
{
int x,y,m=M/a[i];
exgcd(m,a[i],x,y);
x=(x%a[i]+a[i])%a[i];
ret=(ret+mul(mul(m,x,M),b[i],M))%M;
}
return ret;
}
signed main()
{
fin>>n;
for(int i=1;i<=n;i++) fin>>a[i]>>b[i];
fout<<crt();
return 0;
}
excrt
const int N=100010;
int m[N],r[N],n;
int mul(int x,int y,int mod)
{
int ret=0;
while(y)
{
if(y&1) ret=(ret+x)%mod;
x=(x+x)%mod;
y>>=1;
}
return ret;
}
int exgcd(int a,int b,int& x,int& y)
{
if(b==0)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}
int excrt()
{
int M=m[1],ans=r[1],t,y;
for(int i=2;i<=n;i++)
{
int mi=m[i],res=((r[i]-ans)%mi+mi)%mi;
int d=exgcd(M,mi,t,y);
if(res%d!=0) return -1;
t=mul(t,res/d,mi);
ans+=t*M;
M=mi/d*M;
ans=(ans%M+M)%M;
}
return ans;
}
signed main()
{
fin>>n;
for(int i=1;i<=n;i++) fin>>m[i]>>r[i];
fout<<excrt();
return 0;
}
高斯消元法
#define il inline
double a[1010][1010],eps=1e-10;
int n;
bool gauss()
{
int now=1,to;
double t;
for(int i=1;i<=n;i++)
{
for(to=now;to<=n;to++)
{
if(fabs(a[to][i])>eps) break;
}
if(to>n) break;
if(to!=now) swap(a[to],a[now]);
t=a[now][i];
for(int j=1;j<=n+1;j++) a[now][j]/=t;
for(int j=1;j<=n;j++)
{
if(j!=now)
{
t=a[j][i];
for(int k=1;k<=n+1;k++)
{
a[j][k]-=t*a[now][k];
}
}
}
now++;
}
return now>n;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n+1;j++)
{
cin>>a[i][j];
}
}
if(gauss())
{
for(int i=1;i<=n;i++)
{
printf("%.2lf\n",a[i][n+1]);
}
}
else printf("No Solution");
return 0;
}
FFT
const int N=4000010;
const double pi=acos(-1.0);
int limit=1,r[N];
struct Complex
{
double x,y;
} a[N],b[N];
Complex operator +(Complex x,Complex y){return {x.x+y.x,x.y+y.y};}
Complex operator -(Complex x,Complex y){return {x.x-y.x,x.y-y.y};}
Complex operator *(Complex x,Complex y){return {x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x};}
il void FFT(Complex* A,int type)
{
for(int i=0;i<limit;i++) if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
Complex Wn={cos(pi/mid),type*sin(pi/mid)};
for(int len=(mid<<1),i=0;i<limit;i+=len)
{
Complex w={1,0};
for(int j=0;j<mid;j++,w=w*Wn)
{
Complex x=A[i+j],y=w*A[i+j+mid];
A[i+j]=x+y;
A[i+j+mid]=x-y;
}
}
}
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,m,tmp;fin>>n>>m;
for(int i=0;i<=n;i++) fin>>tmp,a[i].x=tmp;
for(int i=0;i<=m;i++) fin>>tmp,b[i].x=tmp;
int l=0;
while(limit<=n+m) limit<<=1,l++;
for(int i=0;i<limit;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
FFT(a,1);FFT(b,1);
for(int i=0;i<limit;i++) a[i]=a[i]*b[i];
FFT(a,-1);
for(int i=0;i<=n+m;i++) fout<<(int)(a[i].x/limit+0.5)<<" ";
return 0;
}
NTT
il int qpow(int x,int y)
{
int ret=1;
while(y)
{
if(y&1) ret=ret*x%mod;
x=x*x%mod;y>>=1;
}
return ret;
}
int inv=qpow(3,mod-2);
il void NTT(int* A,int n,int type)
{
for(int i=0;i<n;i++) if(r[i]>i) swap(A[i],A[r[i]]);
for(int mid=1;mid<n;mid<<=1)
{
int Wn=qpow(type?3:inv,(mod-1)/(mid<<1));
for(int len=(mid<<1),i=0;i<n;i+=len)
{
int w=1;
for(int j=0;j<mid;j++,w=w*Wn%mod)
{
int x=A[i+j],y=w*A[i+j+mid]%mod;
A[i+j]=(x+y)%mod;
A[i+j+mid]=(x-y+mod)%mod;
}
}
}
if(!type)
{
int tmp=qpow(n,mod-2);
for(int i=0;i<n;i++) A[i]=A[i]*tmp%mod;
}
}
多项式乘法逆
const int N=400010,mod=998244353;
int w[N],ans[N],A[N],B[N],r[N];
il int qpow(int x,int y)
{
int ret=1;
while(y)
{
if(y&1) ret=ret*x%mod;
x=x*x%mod;y>>=1;
}
return ret;
}
int inv=qpow(3,mod-2);
il void NTT(int* A,int n,int type)
{
for(int i=0;i<n;i++) if(r[i]>i) swap(A[i],A[r[i]]);
for(int mid=1;mid<n;mid<<=1)
{
int Wn=qpow(type?3:inv,(mod-1)/(mid<<1));
for(int len=(mid<<1),i=0;i<n;i+=len)
{
int w=1;
for(int j=0;j<mid;j++,w=w*Wn%mod)
{
int x=A[i+j],y=w*A[i+j+mid]%mod;
A[i+j]=(x+y)%mod;
A[i+j+mid]=(x-y+mod)%mod;
}
}
}
if(!type)
{
int tmp=qpow(n,mod-2);
for(int i=0;i<n;i++) A[i]=A[i]*tmp%mod;
}
}
il void Inv(int* a,int* b,int n)
{
b[0]=qpow(a[0],mod-2);
for(int lim=2;lim<=n;lim<<=1)
{
// fout<<lim<<"\n";
int len=lim<<1;
for(int i=0;i<lim;i++) A[i]=a[i],B[i]=b[i];
for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)*lim);
NTT(A,len,1);NTT(B,len,1);
for(int i=0;i<len;i++) b[i]=B[i]*(2-A[i]*B[i]%mod+mod)%mod;
NTT(b,len,0);
for(int i=lim;i<len;i++) b[i]=0;
}
}
signed main()
{
int n;fin>>n;
for(int i=0;i<n;i++) fin>>w[i];
Inv(w,ans,n<<1);
for(int i=0;i<n;i++) fout<<ans[i]<<" ";
return 0;
}
多项式开根
const int N=400010,mod=998244353;
int w[N],ans[N],A[N],B[N],C[N],D[N],r[N];
il int qpow(int x,int y)
{
int ret=1;
while(y)
{
if(y&1) ret=ret*x%mod;
x=x*x%mod;y>>=1;
}
return ret;
}
int inv2=qpow(2,mod-2),inv3=qpow(3,mod-2);
il void NTT(int* A,int n,int type)
{
for(int i=0;i<n;i++) if(r[i]>i) swap(A[i],A[r[i]]);
for(int mid=1;mid<n;mid<<=1)
{
int Wn=qpow(type?3:inv3,(mod-1)/(mid<<1));
for(int len=(mid<<1),i=0;i<n;i+=len)
{
int w=1;
for(int j=0;j<mid;j++,w=w*Wn%mod)
{
int x=A[i+j],y=A[i+j+mid]*w%mod;
A[i+j]=(x+y)%mod;
A[i+j+mid]=(x-y+mod)%mod;
}
}
}
if(!type)
{
int tmp=qpow(n,mod-2);
for(int i=0;i<n;i++) A[i]=A[i]*tmp%mod;
}
}
il void Inv(int* a,int* b,int n)
{
b[0]=qpow(a[0],mod-2);
int now=1;
while(now<n)
{
now<<=1;
int len=(now<<1);
for(int i=0;i<now;i++) A[i]=a[i],B[i]=b[i];
for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)*now);
NTT(A,len,1);NTT(B,len,1);
for(int i=0;i<len;i++) b[i]=B[i]*(2-B[i]*A[i]%mod+mod)%mod;
NTT(b,len,0);
for(int i=now;i<len;i++) b[i]=0;
}
for(int i=0;i<(n<<1);i++) A[i]=B[i]=0;
}
il void sqr(int* a,int* b,int n)
{
b[0]=1;
int now=1;
while(now<n)
{
now<<=1;
int len=(now<<1);
for(int i=0;i<now;i++) C[i]=a[i];
Inv(b,D,now);
for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)*now);
NTT(C,len,1);NTT(D,len,1);
for(int i=0;i<len;i++) C[i]=C[i]*D[i]%mod;
NTT(C,len,0);
for(int i=0;i<now;i++) b[i]=inv2*(C[i]+b[i])%mod;
for(int i=now;i<len;i++) b[i]=0;
}
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n;fin>>n;
for(int i=0;i<n;i++) fin>>w[i];
sqr(w,ans,n);
for(int i=0;i<n;i++) fout<<ans[i]<<" ";
return 0;
}
lucas
const int N=100010;
int n,m,mod,jc[N],fjc[N];
int C(int x,int y,int p)
{
if(x<y) return 0;
return jc[x]*fjc[y]%p*fjc[x-y]%p;
}
int lucas(int x,int y,int p)
{
if(y==0) return 1;
return lucas(x/p,y/p,p)*C(x%p,y%p,p)%p;
}
int qpow(int x,int y,int p)
{
int ret=1;
while(y)
{
if(y&1) ret=ret*x%p;
x=x*x%p;
y>>=1;
}
return ret;
}
signed main()
{
int t;
fin>>t;
while(t--)
{
fin>>n>>m>>mod;
jc[0]=1;
for(int i=1;i<mod;i++) jc[i]=jc[i-1]*i%mod;
fjc[mod-1]=qpow(jc[mod-1],mod-2,mod);
for(int i=mod-2;i>=0;i--) fjc[i]=fjc[i+1]*(i+1)%mod;
fout<<lucas(n+m,n,mod)<<"\n";
}
return 0;
}
exlucas
#define ll __int128
ll m[1000010],r[1000010];
int cnt;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll d=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}
ll inv(ll a,ll b)
{
ll x,y;
exgcd(a,b,x,y);
return (x%b+b)%b;
}
ll qpow_mod(ll a,ll b,ll mod)
{
ll ret=1;
while(b)
{
if(b&1) ret=ret*a%mod;
a=a*a%mod;
b>>=1;
}
return ret;
}
ll fac_mod(ll n,ll p,ll pk)
{
if(!n) return 1;
ll ret=1;
for(ll i=1;i<=pk;i++) if(i%p) ret=ret*i%pk;
ret=qpow_mod(ret,n/pk,pk);
for(ll i=1;i<=n%pk;i++) if(i%p) ret=ret*i%pk;
return ret*fac_mod(n/p,p,pk)%pk;
}
ll C_mod(ll n,ll m,ll p,ll pk)
{
ll x=0,y=0,z=0;
for(ll i=p;i<=n;i*=p) x+=n/i;
for(ll i=p;i<=m;i*=p) y+=m/i;
for(ll i=p;i<=n-m;i*=p) z+=(n-m)/i;
return ((fac_mod(n,p,pk)*inv(fac_mod(m,p,pk),pk)%pk)*inv(fac_mod(n-m,p,pk),pk)%pk)*qpow_mod(p,x-y-z,pk)%pk;
}
ll crt(ll m[],ll r[],int n)
{
ll M=1,res=0;
for(int i=1;i<=n;i++) M*=m[i];
for(int i=1;i<=n;i++)
{
ll mod=M/m[i];
res=(res+(mod*inv(mod,m[i])%M)*r[i]%M)%M;
}
return res;
}
ll exlucas(ll n,ll M,ll p)
{
for(ll i=2;i*i<=p;i++)
{
if(p%i==0)
{
ll pk=1;
while(p%i==0)
{
pk*=i;
p/=i;
}
m[++cnt]=pk;
r[cnt]=C_mod(n,M,i,pk);
}
}
if(p!=1)
{
cnt++;
m[cnt]=p;
r[cnt]=C_mod(n,M,p,p);
}
return crt(m,r,cnt);
}
int main()
{
ll n,m,p; fin>>n>>m>>p;
fout<<exlucas(n,m,p);
return 0;
}
杜教筛
const int N=2e6+10;
ll mu[N],phi[N];
struct hashmap
{
static const int MOD=1e7+19;
int h[MOD],cnt;
struct hashnode
{
int nxt;
ll a,b;
} e[N];
void change(ll x,ll y)
{
int c=x%MOD;
for(int i=h[c];i;i=e[i].nxt)
{
if(e[i].a==x)
{
e[i].b=y;
return;
}
}
e[++cnt]={h[c],x,y},h[c]=cnt;
}
bool find(ll x)
{
int c=x%MOD;
for(int i=h[c];i;i=e[i].nxt)
{
if(e[i].a==x) return true;
}
return false;
}
ll operator [](ll x)
{
int c=x%MOD;
for(int i=h[c];i;i=e[i].nxt)
{
if(e[i].a==x) return e[i].b;
}
return 0;
}
} smu,sphi;
int vis[N],p[N],cnt;
void init()
{
mu[1]=1;phi[1]=1;
for(int i=2;i<=N-10;i++)
{
if(!vis[i])
{
p[++cnt]=i;
mu[i]=-1;phi[i]=i-1;
}
for(int j=1;i*p[j]<=N-10;j++)
{
vis[i*p[j]]=1;
if(i%p[j]==0)
{
phi[i*p[j]]=phi[i]*p[j];
break;
}
phi[i*p[j]]=phi[i]*(p[j]-1);
mu[i*p[j]]=-mu[i];
}
}
for(int i=2;i<=N-10;i++) mu[i]+=mu[i-1];
for(int i=2;i<=N-10;i++) phi[i]+=phi[i-1];
}
ll get_sphi(ll n)
{
if(n<=N-10) return phi[n];
if(sphi.find(n)) return sphi[n];
ll ret=1ll*(n+1)*n/2;
for(ll l=2,r;l<=n;l=r+1)
{
r=n/(n/l);
ret-=1ll*(r-l+1)*get_sphi(n/l);
}
sphi.change(n,ret);
return ret;
}
ll get_smu(ll n)
{
if(n<=N-10) return mu[n];
if(smu.find(n)) return smu[n];
ll ret=1;
for(ll l=2,r;l<=n;l=r+1)
{
r=n/(n/l);
ret-=1ll*(r-l+1)*get_smu(n/l);
}
smu.change(n,ret);
return ret;
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
init();
int t;fin>>t;
while(t--)
{
ll n;fin>>n;
fout<<get_sphi(n)<<" "<<get_smu(n)<<"\n";
}
return 0;
}
自适应辛普森积分
const double eps=1e-6;
double a,b,c,d;
double F(double x)
{
return (c*x+d)/(a*x+b);
}
il double Simpson(double l,double r)
{
double mid=(l+r)/2;
return (r-l)/6*(F(l)+F(r)+4*F(mid));
}
il double asr(double l,double r,double lst,double eps,int dep)
{
double mid=(l+r)/2;
double Lv=Simpson(l,mid),Rv=Simpson(mid,r),t;
if(dep<=0 && fabs(t=Lv+Rv-lst)<=15*eps) return Lv+Rv+t/15;
return asr(l,mid,Lv,eps/2,dep-1)+asr(mid,r,Rv,eps/2,dep-1);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
double l,r;cin>>a>>b>>c>>d>>l>>r;
cout<<fixed<<setprecision(6)<<asr(l,r,Simpson(l,r),eps,10);
return 0;
}
Min_25筛
const int N=200010,mod=1e9+7;
int n,m,vis[N],prime[N],cnt,Id1[N],Id2[N],val[N],tot,g1[N],g2[N];
il int get_id(int x){return x<=m?Id1[x]:Id2[n/x];}
il int qpow(int x,int y)
{
int ret=1;
while(y)
{
if(y&1) ret=ret*x%mod;
x=x*x%mod;y>>=1;
}
return ret;
}
int inv2=qpow(2,mod-2),inv6=qpow(6,mod-2);
il void init()
{
for(int i=2;i<=m;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
for(int j=i+i;j<=m;j+=i) vis[j]=1;
}
}
for(int l=1,r=0;l<=n;l=r+1)
{
r=n/(n/l);
int tmp=n/l;
val[++tot]=tmp;
if(tmp<=m) Id1[tmp]=tot;
else Id2[n/tmp]=tot;
tmp%=mod;
g1[tot]=((tmp+1)*tmp%mod*inv2%mod+mod-1)%mod;
g2[tot]=((tmp+1)*tmp%mod*(2*tmp+1)%mod*inv6%mod+mod-1)%mod;
}
for(int j=1;j<=cnt;j++)
{
for(int i=1;i<=tot&&val[i]>=prime[j]*prime[j];i++)
{
int id1=get_id(val[i]/prime[j]),id2=get_id(prime[j-1]);
g1[i]-=prime[j]*(g1[id1]-g1[id2])%mod;
g2[i]-=prime[j]*prime[j]%mod*(g2[id1]-g2[id2])%mod;
g1[i]=(g1[i]%mod+mod)%mod;
g2[i]=(g2[i]%mod+mod)%mod;
}
}
}
il int F(int x){x%=mod;return (x*x-x+mod)%mod;}
il int S(int N,int j)
{
if(prime[j]>N) return 0;
// cout<<N<<" "<<prime[j]<<"\n";
int id1=get_id(N),id2=get_id(prime[j]);
int ret=(g2[id1]-g1[id1])-(g2[id2]-g1[id2]);
ret=(ret%mod+mod)%mod;
for(int k=j+1;k<=cnt && prime[k]*prime[k]<=N;k++)
{
for(int num=prime[k],e=1;num<=N;num*=prime[k],e++)
{
ret=(ret+F(num)*(S(N/num,k)+(e!=1)))%mod;
}
}
return ret;
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
fin>>n;m=sqrt(n);
init();
fout<<(S(n,0)+1)%mod<<"\n";
return 0;
}
求原根
const int N=1000010;
int phi[N],prime[N],cnt,vis[N];
vector<int> root,p;
il bool exist_root(int n)
{
if(n==2 || n==4) return 1;
if(n%2==0)
{
n/=2;
if(n%2==0) return 0;
}
int cnt=0,tmp=n;
for(int i=2;i*i<=n;i++)
{
if(tmp%i==0)
{
cnt++;
while(tmp%i==0) tmp/=i;
}
}
if(tmp!=1) cnt++;
return cnt==1;
}
il int qpow(int x,int y,int mod)
{
int ret=1;
while(y)
{
if(y&1) ret=ret*x%mod;
x=x*x%mod;y>>=1;
}
return ret;
}
il int get_minroot(int n)
{
vector<int> ().swap(p);
int tmp=phi[n];
for(int i=2;i*i<=phi[n];i++)
{
if(tmp%i==0)
{
p.push_back(i);
while(tmp%i==0) tmp/=i;
}
}
if(tmp!=1) p.push_back(tmp);
for(int i=1;i<=n;i++)
{
int fl=1;
if(qpow(i,phi[n],n)!=1) continue;
for(int j:p)
{
if(qpow(i,phi[n]/j,n)==1)
{
fl=0;
break;
}
}
if(fl) return i;
}
return -1;
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int t;fin>>t;
phi[1]=1;
for(int i=2;i<=1e6;i++)
{
if(!vis[i]) phi[i]=i-1,prime[++cnt]=i;
for(int j=1;j<=cnt;j++)
{
int tmp=prime[j]*i;
if(tmp>1e6) break;
vis[tmp]=1;
if(i%prime[j]==0)
{
phi[tmp]=phi[i]*prime[j];
break;
}
phi[tmp]=phi[i]*(prime[j]-1);
}
}
while(t--)
{
int n,d;fin>>n>>d;
vector<int> ().swap(root);
if(!exist_root(n)) fout<<0<<"\n\n";
else
{
int g=get_minroot(n);
for(int i=1;i<=phi[n];i++)
{
if(__gcd(i,phi[n])!=1) continue;
root.push_back(qpow(g,i,n));
}
sort(root.begin(),root.end());
fout<<root.size()<<"\n";
for(int i=1;i<=(int)root.size()/d;i++)
{
fout<<root[i*d-1]<<" ";
}
fout<<"\n";
}
}
return 0;
}
数据结构
普通莫队
int cnt[50010],a[50010],b[50010],x,res,ans[50010];
struct question
{
int l,r,idx;
} q[50010];
bool cmp(question x,question y)
{
if(b[x.l]!=b[y.l])
{
return b[x.l]<b[y.l];
}
if(b[x.l]&1) return x.r<y.r;
else return x.r>x.r;
}
void add(int i)
{
res+=cnt[a[i]]*2+1;
cnt[a[i]]++;
}
void del(int i)
{
res-=cnt[a[i]]*2-1;
cnt[a[i]]--;
}
int main()
{
int n,m,k;
cin>>n>>m>>k;
x=sqrt(n);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) b[i]=(i-1)/x+1;
for(int i=1;i<=m;i++)
{
cin>>q[i].l>>q[i].r;
q[i].idx=i;
}
sort(q+1,q+1+m,cmp);
int L=1,R=1;
res=1;
cnt[a[1]]=1;
for(int i=1;i<=m;i++)
{
while(L>q[i].l) add(--L);
while(R<q[i].r) add(++R);
while(L<q[i].l) del(L++);
while(R>q[i].r) del(R--);
ans[q[i].idx]=res;
}
for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
return 0;
}
带修莫队
const int N=150010;
int b[N],a[N],cntq,tim,B,cnt[1000010],ret,ans[N];
struct qwq
{
int tim,idx,l,r;
} q[N];
struct node
{
int pos,val;
} c[N];
bool cmp(qwq x,qwq y)
{
return tie(b[x.l],b[x.r],x.tim)<tie(b[y.l],b[y.r],y.tim);
}
void add(int x)
{
if(cnt[a[x]]==0) ret++;
cnt[a[x]]++;
}
void del(int x)
{
if(cnt[a[x]]==1) ret--;
cnt[a[x]]--;
}
void change(int x,int l,int r)
{
int idx=c[x].pos;
if(l<=idx && idx<=r)
{
if(cnt[a[idx]]==1) ret--;
cnt[a[idx]]--;
if(cnt[c[x].val]==0) ret++;
cnt[c[x].val]++;
}
swap(c[x].val,a[idx]);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,m;fin>>n>>m;B=pow(n,0.66);
for(int i=1;i<=n;i++) fin>>a[i];
for(int i=1;i<=n;i++) b[i]=(i-1)/B+1;
while(m--)
{
char op;int x,y;fin>>op>>x>>y;
if(op=='Q')
{
cntq++;
q[cntq]={tim,cntq,x,y};
}
else
{
tim++;
c[tim]={x,y};
}
}
sort(q+1,q+1+cntq,cmp);
int L=1,R=0,now=0;
for(int i=1;i<=cntq;i++)
{
while(R<q[i].r) add(++R);
while(L>q[i].l) add(--L);
while(R>q[i].r) del(R--);
while(L<q[i].l) del(L++);
while(now<q[i].tim) change(++now,q[i].l,q[i].r);
while(now>q[i].tim) change(now--,q[i].l,q[i].r);
ans[q[i].idx]=ret;
}
for(int i=1;i<=cntq;i++) fout<<ans[i]<<"\n";
return 0;
}
WBLT
const int N=100010;
const double Alpha=0.3;
int pool[N],top,tot,son[N][2],siz[N],val[N],rt;
void push_up(int x)
{
siz[x]=siz[son[x][0]]+siz[son[x][1]];
val[x]=val[son[x][1]];
}
int new_node()
{
int x=top?pool[top--]:++tot;
son[x][0]=son[x][1]=val[x]=siz[x]=0;
return x;
}
void del_node(int& x)
{
pool[++top]=x;
x=0;
}
int new_leaf(int v)
{
int x=new_node();
val[x]=v;siz[x]=1;
return x;
}
int join(int x,int y)
{
int z=new_node();
son[z][0]=x;son[z][1]=y;
push_up(z);
return z;
}
auto cut(int& z)
{
int x=son[z][0],y=son[z][1];
del_node(z);
return make_pair(x,y);
}
void rotate(int& x,int r)
{
int a,b,c,d;
tie(a,b)=cut(x);
if(r)
{
tie(c,d)=cut(b);
x=join(join(a,c),d);
}
else
{
tie(c,d)=cut(a);
x=join(c,join(d,b));
}
}
bool too_heavy(int sx,int sy)
{
return sy<Alpha*(sx+sy);
}
bool need_two(int x,bool r)
{
return siz[son[x][!r]]>siz[x]/(2-Alpha);
}
void balance(int& x)
{
if(siz[x]==1) return;
bool r=siz[son[x][1]]>siz[son[x][0]];
if(!too_heavy(siz[son[x][r]],siz[son[x][!r]])) return;
if(need_two(son[x][r],r)) rotate(son[x][r],!r);
rotate(x,r);
}
void insert(int& x,int v)
{
if(!x)
{
x=new_leaf(v);
return;
}
else if(siz[x]==1)
{
bool r=v>=val[x];
son[x][r]=new_leaf(v);
son[x][!r]=new_leaf(val[x]);
push_up(x);
return;
}
else
{
if(v<=val[son[x][0]]) insert(son[x][0],v);
else insert(son[x][1],v);
push_up(x);
balance(x);
}
}
void remove(int& x,int v)
{
if(siz[x]==1) del_node(x);
else
{
bool r=v>val[son[x][0]];
remove(son[x][r],v);
if(!siz[son[x][r]]) x=son[x][!r];
else push_up(x),balance(x);
}
}
int get_cnt(int x,int w)
{
if(!x) return 0;
if(siz[x]==1) return val[x]<w;
if(w<=val[son[x][0]]) return get_cnt(son[x][0],w);
else return siz[son[x][0]]+get_cnt(son[x][1],w);
}
int get_num(int x,int w)
{
if(siz[x]==1) return val[x];
if(w<=siz[son[x][0]]) return get_num(son[x][0],w);
else return get_num(son[x][1],w-siz[son[x][0]]);
}
signed main()
{
// freopen("P3369_5.in","r",stdin);
// freopen("chj.out","w",stdout);
int q;fin>>q;
while(q--)
{
int op,x;fin>>op>>x;
if(op==1) insert(rt,x);
else if(op==2) remove(rt,x);
else if(op==3) fout<<get_cnt(rt,x)+1<<"\n";
else if(op==4) fout<<get_num(rt,x)<<"\n";
else if(op==5) fout<<get_num(rt,get_cnt(rt,x))<<"\n";
else fout<<get_num(rt,get_cnt(rt,x+1)+1)<<"\n";
}
return 0;
}
区间WBLT
const int N=100010;
const double Alpha=0.292;
int lazy[N<<1],val[N<<1],siz[N<<1],son[N<<1][2],pool[N<<1],top,tot,rt;
il void push_up(int x)
{
siz[x]=siz[son[x][0]]+siz[son[x][1]];
}
il int new_node()
{
int x=top?pool[top--]:++tot;
siz[x]=lazy[x]=son[x][0]=son[x][1]=val[x]=0;
return x;
}
il void del_node(int& x)
{
pool[++top]=x;x=0;
}
il int new_leaf(int v)
{
int x=new_node();
val[x]=v;siz[x]=1;
return x;
}
il int join(int x,int y)
{
int z=new_node();
son[z][0]=x;son[z][1]=y;
push_up(z);
return z;
}
il void lazy_reverse(int x)
{
if(!x) return;
lazy[x]^=1;
swap(son[x][0],son[x][1]);
}
il void push_down(int x)
{
if(lazy[x])
{
lazy_reverse(son[x][0]);
lazy_reverse(son[x][1]);
lazy[x]=0;
}
}
il auto cut(int& x)
{
push_down(x);
int y=son[x][0],z=son[x][1];
del_node(x);
return make_pair(y,z);
}
il void rotate(int& x,bool r)
{
int a,b,c,d;
tie(a,b)=cut(x);
if(r)
{
tie(c,d)=cut(b);
x=join(join(a,c),d);
}
else
{
tie(c,d)=cut(a);
x=join(c,join(d,b));
}
}
il bool too_heavy(int sx,int sy)
{
return sy<Alpha*(sx+sy);
}
il bool need_two(int x,bool r)
{
return siz[son[x][!r]]>siz[x]/(2-Alpha);
}
il void balance(int& x)
{
if(siz[x]==1) return;
push_down(x);
bool r=siz[son[x][1]]>siz[son[x][0]];
if(!too_heavy(siz[son[x][r]],siz[son[x][!r]])) return;
push_down(son[x][r]);
if(need_two(son[x][r],r))
{
push_down(son[son[x][r]][!r]);
rotate(son[x][r],!r);
}
rotate(x,r);
}
il int merge(int x,int y)
{
if(!x || !y) return x|y;
int a,b;
if(too_heavy(siz[x],siz[y]))
{
tie(a,b)=cut(x);
x=join(a,merge(b,y));
balance(x);
return x;
}
else if(too_heavy(siz[y],siz[x]))
{
tie(a,b)=cut(y);
x=join(merge(x,a),b);
balance(x);
return x;
}
else return join(x,y);
}
il pair<int,int> split(int x,int k)
{
if(!x) return {0,0};
if(!k) return {0,x};
if(k==siz[x]) return {x,0};
int a,b;
tie(a,b)=cut(x);
if(k<=siz[a])
{
int ll,rr;
tie(ll,rr)=split(a,k);
return {ll,merge(rr,b)};
}
else
{
int ll,rr;
k-=siz[a];
tie(ll,rr)=split(b,k);
return {merge(a,ll),rr};
}
}
il void reverse(int l,int r)
{
int ll,rr;
tie(ll,rr)=split(rt,r);
tie(ll,rt)=split(ll,l-1);
lazy_reverse(rt);
rt=merge(merge(ll,rt),rr);
}
il int build(int l,int r)
{
if(l==r) return new_leaf(l);
int mid=(l+r)>>1;
return join(build(l,mid),build(mid+1,r));
}
il void print(int x)
{
if(siz[x]==1)
{
fout<<val[x]<<" ";
return;
}
push_down(x);
print(son[x][0]);
print(son[x][1]);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,m,l,r;fin>>n>>m;
rt=build(1,n);
while(m--)
{
fin>>l>>r;
reverse(l,r);
}
print(rt);
return 0;
}
可持久化WBLT
const int N=500010;
const double Alpha=0.292;
int rt[N],pool[N<<5],tp,tot;
struct node
{
int son[2],val,siz,use;
} t[N<<5];
il int new_node(int x)
{
int id=tp?pool[tp--]:++tot;
t[id].use=t[id].siz=1;
t[id].val=x;
t[id].son[0]=t[id].son[1]=0;
return id;
}
il void push_up(int id)
{
t[id].siz=t[t[id].son[0]].siz+t[t[id].son[1]].siz;
t[id].val=t[t[id].son[1]].val;
}
il void del_node(int& id)
{
pool[++tp]=id;
id=0;
}
il int join(int x,int y)
{
int z=new_node(0);
t[z].son[0]=x,t[z].son[1]=y;
push_up(z);
return z;
}
il void clone(int x,int y)
{
t[x].son[0]=t[y].son[0];
t[x].son[1]=t[y].son[1];
t[x].siz=t[y].siz;
t[x].val=t[y].val;
if(t[x].son[0])
{
t[t[x].son[0]].use++;
t[t[x].son[1]].use++;
}
}
il void refresh(int& x)
{
if(t[x].use==1 || !x) return;
t[x].use--;
int y=x;x=new_node(0);
clone(x,y);
}
il auto cut(int& x)
{
refresh(x);
int y=t[x].son[0],z=t[x].son[1];
del_node(x);
return make_pair(y,z);
}
il void rotate(int& x,bool r)
{
int a,b,c,d;
tie(a,b)=cut(x);
if(r)
{
tie(c,d)=cut(b);
x=join(join(a,c),d);
}
else
{
tie(c,d)=cut(a);
x=join(c,join(d,b));
}
}
il bool too_heavy(int sx,int sy)
{
return sy<Alpha*(sx+sy);
}
il bool need_two(int x,bool r)
{
return t[t[x].son[!r]].siz>=t[x].siz/(2-Alpha);
}
il void balance(int& x)
{
if(!t[x].son[0]) return;
refresh(x);
bool r=t[t[x].son[1]].siz>t[t[x].son[0]].siz;
if(!too_heavy(t[t[x].son[r]].siz,t[t[x].son[!r]].siz)) return;
refresh(t[x].son[r]);
if(need_two(t[x].son[r],r))
{
// refresh(t[t[x].son[r]].son[!r]);
rotate(t[x].son[r],!r);
}
rotate(x,r);
}
il void ins(int& x,int v)
{
refresh(x);
if(!x) x=new_node(v);
else if(!t[x].son[0])
{
bool r=v>t[x].val;
t[x].son[r]=new_node(v);
t[x].son[!r]=new_node(t[x].val);
push_up(x);
}
else
{
bool r=v>t[t[x].son[0]].val;
ins(t[x].son[r],v);
push_up(x);
balance(x);
}
}
il void del(int& x,int v)
{
refresh(x);
if(!x) return;
if(!t[x].son[0])
{
if(t[x].val==v) del_node(x);
}
else
{
bool r=v>t[t[x].son[0]].val;
del(t[x].son[r],v);
if(!t[x].son[r]) x=t[x].son[!r];
else push_up(x),balance(x);
}
}
il int query_num(int x,int v)
{
if(!t[x].son[0]) return t[x].val;
else
{
int w=t[t[x].son[0]].siz;
if(v<=w) return query_num(t[x].son[0],v);
else return query_num(t[x].son[1],v-w);
}
}
il int query_sum(int x,int v)
{
// if(!x) return 0;
if(!t[x].son[0]) return t[x].val<v;
else
{
int w=t[t[x].son[0]].val;
if(w<v) return t[t[x].son[0]].siz+query_sum(t[x].son[1],v);
else return query_sum(t[x].son[0],v);
}
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int q;fin>>q;
for(int u=1;u<=q;u++)
{
int v,op,x;fin>>v>>op>>x;
t[rt[u]=rt[v]].use++;
if(op==1) ins(rt[u],x);
else if(op==2) del(rt[u],x);
else if(op==3) fout<<query_sum(rt[u],x)+1<<"\n";
else if(op==4) fout<<query_num(rt[u],x)<<"\n";
else if(op==5)
{
int val=query_sum(rt[u],x);
if(val==0) fout<<"-2147483647\n";
else fout<<query_num(rt[u],val)<<"\n";
}
else if(op==6)
{
int val=query_sum(rt[u],x+1);
if(val==t[rt[u]].siz) fout<<"2147483647\n";
else fout<<query_num(rt[u],val+1)<<"\n";
}
}
return 0;
}
可持久化区间WBLT
const int N=200010;
const double Alpha=0.292;
int use[N*70],lazy[N*70],siz[N*70],pool[N*70],son[N*70][2],top,tot,rt[N];
LL sum[N*70];
il void push_up(int x)
{
if(!son[x][0]) return;
sum[x]=sum[son[x][0]]+sum[son[x][1]];
siz[x]=siz[son[x][0]]+siz[son[x][1]];
}
il int new_node(int v)
{
int x=top?pool[top--]:++tot;
siz[x]=use[x]=1;sum[x]=v;
lazy[x]=son[x][0]=son[x][1]=0;
return x;
}
il void del_node(int& x) {pool[++top]=x;x=0;}
il int join(int x,int y)
{
int z=new_node(0);
son[z][0]=x;son[z][1]=y;
push_up(z);
return z;
}
il void refresh(int& x)
{
if(!x || use[x]<=1) return;
use[x]--;
int y=x;x=new_node(0);
sum[x]=sum[y];
siz[x]=siz[y];
son[x][0]=son[y][0];
son[x][1]=son[y][1];
lazy[x]=lazy[y];
if(son[x][0])
{
use[son[x][0]]++;
use[son[x][1]]++;
}
}
il void lazy_reverse(int& x)
{
if(!son[x][0]) return;
refresh(x);
lazy[x]^=1;
}
il void push_down(int x)
{
if(!lazy[x] || !son[x][0]) return;
lazy_reverse(son[x][0]);lazy_reverse(son[x][1]);
swap(son[x][0],son[x][1]);
lazy[x]=0;
}
il auto cut(int& x)
{
refresh(x);
push_down(x);
int y=son[x][0],z=son[x][1];
del_node(x);
return make_pair(y,z);
}
il void rotate(int& x,bool r)
{
int a,b,c,d;
tie(a,b)=cut(x);
if(r)
{
tie(c,d)=cut(b);
x=join(join(a,c),d);
}
else
{
tie(c,d)=cut(a);
x=join(c,join(d,b));
}
}
il bool too_heavy(int sx,int sy)
{
return sy<Alpha*(sx+sy);
}
il bool need_two(int x,bool r)
{
return siz[son[x][!r]]>siz[x]/(2-Alpha);
}
il void balance(int& x)
{
if(!son[x][0]) return;
refresh(x);
push_down(x);
bool r=siz[son[x][1]]>siz[son[x][0]];
if(!too_heavy(siz[son[x][r]],siz[son[x][!r]])) return;
refresh(son[x][r]);
push_down(son[x][r]);
if(need_two(son[x][r],r))
{
refresh(son[son[x][r]][!r]);
push_down(son[son[x][r]][!r]);
rotate(son[x][r],!r);
}
rotate(x,r);
}
il void add(int& x,int k,int v)
{
refresh(x);
push_down(x);
if(!son[x][0])
{
son[x][0]=new_node(v);
son[x][1]=new_node(sum[x]);
push_up(x);
return;
}
else
{
if(k<=siz[son[x][0]]) add(son[x][0],k,v);
else add(son[x][1],k-siz[son[x][0]],v);
push_up(x);
balance(x);
}
}
il void del(int& x,int k)
{
refresh(x);
push_down(x);
if(!son[x][0])
{
del_node(x);
return;
}
else
{
bool r=k>siz[son[x][0]];
if(r) k-=siz[son[x][0]];
del(son[x][r],k);
if(!son[x][r]) x=son[x][!r];
push_up(x);
balance(x);
}
}
il int merge(int x,int y)
{
if(!x || !y) return x|y;
int a,b;
if(too_heavy(siz[x],siz[y]))
{
tie(a,b)=cut(x);
x=join(a,merge(b,y));
balance(x);
return x;
}
else if(too_heavy(siz[y],siz[x]))
{
tie(a,b)=cut(y);
x=join(merge(x,a),b);
balance(x);
return x;
}
else return join(x,y);
}
il pair<int,int> split(int x,int k)
{
if(!x) return {0,0};
if(!k) return {0,x};
if(k==siz[x]) return {x,0};
int a,b,ll,rr;
tie(a,b)=cut(x);
if(k<=siz[a])
{
tie(ll,rr)=split(a,k);
return {ll,merge(rr,b)};
}
else
{
k-=siz[a];
tie(ll,rr)=split(b,k);
return {merge(a,ll),rr};
}
}
il void reverse(int& x,int l,int r)
{
int ll,rr;
tie(ll,rr)=split(x,r);
tie(ll,x)=split(ll,l-1);
refresh(x);
lazy_reverse(x);
x=merge(merge(ll,x),rr);
}
il LL query_sum(int& x,int l,int r)
{
int ll,rr;
LL ret=0;
tie(ll,rr)=split(x,r);
tie(ll,x)=split(ll,l-1);
ret=sum[x];
x=merge(merge(ll,x),rr);
return ret;
}
signed main()
{
// freopen("P5055_7.in","r",stdin);
// freopen("chj.out","w",stdout);
int n;fin>>n;
LL lstans=0;
rt[0]=new_node(0);
for(int i=1;i<=n;i++)
{
int v,op;fin>>v>>op;
rt[i]=rt[v];use[rt[i]]++;
if(op==1)
{
LL p,x;fin>>p>>x;
p^=lstans;x^=lstans;
add(rt[i],p+1,x);
}
else if(op==2)
{
LL p;fin>>p;p^=lstans;
del(rt[i],p);
}
else if(op==3)
{
LL l,r;fin>>l>>r;
l^=lstans;r^=lstans;
reverse(rt[i],l,r);
}
else
{
LL l,r;fin>>l>>r;
l^=lstans;r^=lstans;
fout<<(lstans=query_sum(rt[i],l,r))<<"\n";
}
}
return 0;
}
splay
const int N=100010;
int rt=0,son[N][2],fa[N],siz[N],cnt[N],val[N],tot;
int dir(int x){return x==son[fa[x]][1];}
void push_up(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];}
void rotate(int x)
{
int y=fa[x],z=fa[y];
bool r=dir(x);
son[y][r]=son[x][!r];
son[x][!r]=y;
if(z) son[z][dir(y)]=x;
if(son[y][r]) fa[son[y][r]]=y;
fa[y]=x;fa[x]=z;
push_up(y);push_up(x);
}
void splay(int& z,int x)
{
int w=fa[z];
for(int y;(y=fa[x])!=w;rotate(x))
{
if(fa[y]!=w) rotate((dir(x)==dir(y))?y:x);
}
z=x;
}
void find(int& z,int v)
{
int x=z,y=fa[x];
while(1)
{
if(val[x]==v) break;
y=x;
x=son[x][v>val[x]];
if(!x) break;
}
splay(z,x?x:y);
}
void loc(int& z,int k)
{
int x=z;
while(1)
{
if(siz[son[x][0]]>=k) x=son[x][0];
else if(siz[son[x][0]]+cnt[x]>=k) break;
else
{
k-=siz[son[x][0]]+cnt[x];
x=son[x][1];
}
}
splay(z,x);
}
int get_num(int x)
{
if(x>siz[rt]) return -1;
loc(rt,x);
return val[rt];
}
int merge(int x,int y)
{
if(!x || !y) return x|y;
loc(y,1);
son[y][0]=x;
fa[x]=y;
push_up(y);
return y;
}
void ins(int v)
{
int x=rt,y=0;
while(1)
{
if(val[x]==v) break;
y=x;x=son[x][v>val[x]];
if(x==0) break;
}
if(x)
{
cnt[x]++;
siz[x]++;
}
else
{
x=++tot;
val[x]=v;
cnt[x]=siz[x]=1;
fa[x]=y;
if(y) son[y][v>val[y]]=x;
}
splay(rt,x);
}
void del(int v)
{
find(rt,v);
if(!rt || v!=val[rt]) return;
cnt[rt]--;siz[rt]--;
if(!cnt[rt])
{
int x=son[rt][0];
int y=son[rt][1];
fa[x]=fa[y]=0;
rt=merge(x,y);
}
}
int get_rank(int v)
{
find(rt,v);
return siz[son[rt][0]]+(val[rt]<v?cnt[rt]:0)+1;
}
int get_prev(int v)
{
find(rt,v);
if(rt && val[rt]<v) return val[rt];
loc(son[rt][0],siz[son[rt][0]]);
return val[son[rt][0]];
}
int get_next(int v)
{
find(rt,v);
if(rt && val[rt]>v) return val[rt];
loc(son[rt][1],1);
return val[son[rt][1]];
}
signed main()
{
// freopen("P3369_4.in","r",stdin);
// freopen("chj.out","w",stdout);
int q;fin>>q;
while(q--)
{
int op,x;
fin>>op>>x;
if(op==1) ins(x);
else if(op==2)del(x);
else if(op==3) fout<<get_rank(x)<<"\n";
else if(op==4) fout<<get_num(x)<<"\n";
else if(op==5) fout<<get_prev(x)<<"\n";
else fout<<get_next(x)<<"\n";
}
return 0;
}
区间splay(是指针)
int n,m;
struct TreeNode
{
int lazy,siz,val;
TreeNode* son[2];
TreeNode* fa;
};
TreeNode* rt=nullptr;
int dir(TreeNode* x)
{
if(x->fa==nullptr) return 0;
return x==x->fa->son[1];
}
void push_up(TreeNode* x)
{
x->siz=1+((x->son[0]==nullptr)?0:x->son[0]->siz)+((x->son[1]==nullptr)?0:x->son[1]->siz);
}
void rotate(TreeNode* x)
{
TreeNode* y=x->fa;
TreeNode* z=(y==nullptr)?nullptr:y->fa;
int r=dir(x);
y->son[r]=x->son[!r];
x->son[!r]=y;
if(z!=nullptr) z->son[dir(y)]=x;
if(y->son[r]!=nullptr) y->son[r]->fa=y;
x->fa=z;
y->fa=x;
push_up(y);
push_up(x);
}
void splay(TreeNode*& z,TreeNode* x)
{
TreeNode* w=(z==nullptr)?nullptr:z->fa;
for(TreeNode* y;(y=x->fa)!=w;rotate(x))
{
if(y->fa!=w) rotate((dir(x)==dir(y))?y:x);
}
z=x;
}
void build()
{
TreeNode* y;
for(int i=1;i<=n+2;i++)
{
TreeNode* x=new TreeNode;
if(i==1) y=x;
x->son[0]=rt;
x->son[1]=nullptr;
x->val=i-1;
x->lazy=0;
if(rt!=nullptr) rt->fa=x;
rt=x;
push_up(x);
}
splay(rt,y);
}
void lazy_reverse(TreeNode* x)
{
swap(x->son[0],x->son[1]);
x->lazy^=1;
}
void push_down(TreeNode* x)
{
if(x->lazy==1)
{
if(x->son[0]!=nullptr) lazy_reverse(x->son[0]);
if(x->son[1]!=nullptr) lazy_reverse(x->son[1]);
x->lazy=0;
}
}
void loc(TreeNode*& z,int rk)
{
TreeNode* x=z;
while(1)
{
push_down(x);
if(rk<=((x->son[0]==nullptr)?0:x->son[0]->siz))
{
x=x->son[0];
}
else if(rk==((x->son[0]==nullptr)?0:x->son[0]->siz)+1) break;
else
{
rk-=((x->son[0]==nullptr)?0:x->son[0]->siz)+1;
x=x->son[1];
}
}
splay(z,x);
}
void reverse(int l,int r)
{
loc(rt,l);
loc(rt->son[1],r-l+2);
TreeNode* x=(rt->son[1]==nullptr)?nullptr:rt->son[1]->son[0];
lazy_reverse(x);
push_down(x);
splay(rt,x);
}
void prin(TreeNode* x)
{
if(x==nullptr) return;
push_down(x);
prin(x->son[0]);
cout<<x->val<<" ";
prin(x->son[1]);
}
void print()
{
loc(rt,1);
loc(rt->son[1],n+1);
prin(rt->son[1]->son[0]);
}
int main()
{
cin>>n>>m;
build();
while(m--)
{
int l,r;
cin>>l>>r;
reverse(l,r);
}
print();
return 0;
}
替罪羊树
const int N=100010;
const double Alpha=0.7;
int tot_active,id,rt,n_tmp,a[N];
struct node
{
int tot,cnt,siz,val,lid,rid;
} t[N];
il void push_up(int x)
{
t[x].siz=t[t[x].lid].siz+t[t[x].rid].siz+t[x].cnt;
t[x].tot=t[t[x].lid].tot+t[t[x].rid].tot+1;
}
il void flatten(int x)
{
if(!x) return;
flatten(t[x].lid);
if(t[x].cnt) a[++n_tmp]=x;
flatten(t[x].rid);
}
il int build(int l,int r)
{
if(l>r) return 0;
int mid=(l+r)>>1;
int x=a[mid];
t[x].lid=build(l,mid-1);
t[x].rid=build(mid+1,r);
push_up(x);
return x;
}
il void rebuild(int& x)
{
n_tmp=0;
flatten(x);
x=build(1,n_tmp);
}
il bool ins(int& x,int v,int dep)
{
bool check=false;
if(!x)
{
x=++id;
t[x].val=v;
check=dep>log(t[rt].tot+1)/log(1/Alpha);
}
if(t[x].val==v)
{
if(!t[x].cnt) tot_active++;
t[x].cnt++;
}
else if(v<t[x].val) check=ins(t[x].lid,v,dep+1);
else check=ins(t[x].rid,v,dep+1);
push_up(x);
if(check && max(t[t[x].lid].tot,t[t[x].rid].tot)>Alpha*t[x].tot)
{
rebuild(x);
return false;
}
return check;
}
il bool del(int x,int v)
{
if(!x) return false;
int flag=1;
if(v<t[x].val) flag=del(t[x].lid,v);
else if(v>t[x].val) flag=del(t[x].rid,v);
else if(t[x].cnt)
{
t[x].cnt--;
if(!t[x].cnt) tot_active--;
}
else flag=0;
push_up(x);
return flag;
}
il int query_rk(int x,int v)
{
// fout<<t[x].val<<"!@#\n";
if(!x) return 0;
if(v<=t[x].val) return query_rk(t[x].lid,v);
else if(v>t[x].val) return t[t[x].lid].siz+t[x].cnt+query_rk(t[x].rid,v);
}
il int query_kth(int x,int v)
{
// cout<<t[x].siz<<" "<<v<<"\n";
if(v<=t[t[x].lid].siz) return query_kth(t[x].lid,v);
else if(v>t[t[x].lid].siz+t[x].cnt) return query_kth(t[x].rid,v-(t[t[x].lid].siz+t[x].cnt));
else return t[x].val;
}
il void ins_node(int x)
{
ins(rt,x,0);
}
il void del_node(int x)
{
bool flag=del(rt,x);
if(!tot_active) rt=0;
else if(flag && tot_active<t[rt].tot*Alpha) rebuild(rt);
}
il int get_rk(int x)
{
return query_rk(rt,x)+1;
}
il int get_kth(int x)
{
return query_kth(rt,x);
}
signed main()
{
// freopen("input4.in","r",stdin);
// freopen(".out","w",stdout);
int q;fin>>q;
while(q--)
{
int op,x;fin>>op>>x;
// cout<<op<<" "<<x<<"\n";
if(op==1) ins_node(x);
if(op==2) del_node(x);
if(op==3) fout<<get_rk(x)<<"\n";
if(op==4) fout<<get_kth(x)<<"\n";
if(op==5) fout<<get_kth(get_rk(x)-1)<<"\n";
if(op==6) fout<<get_kth(get_rk(x+1))<<"\n";
// fout<<t[rt].tot<<" "<<t[rt].siz<<"\n";
}
return 0;
}
无旋treap
struct TreeNode
{
int val,siz,rank,cnt;
TreeNode* son[2];
};
TreeNode* rt=nullptr;
void push_up(TreeNode* x)
{
x->siz=((x->son[0]==nullptr)?0:x->son[0]->siz)+((x->son[1]==nullptr)?0:x->son[1]->siz)+x->cnt;
}
pair<TreeNode*,TreeNode*> split(TreeNode* x,int w)
{
if(x==nullptr) return {nullptr,nullptr};
if(x->val<=w)
{
auto temp=split(x->son[1],w);
x->son[1]=temp.first;
push_up(x);
return {x,temp.second};
}
else
{
auto temp=split(x->son[0],w);
x->son[0]=temp.second;
push_up(x);
return {temp.first,x};
}
}
pair<TreeNode*,pair<TreeNode*,TreeNode*>> split_by_rk(TreeNode* x,int rk)
{
if(x==nullptr) return {nullptr,{nullptr,nullptr}};
int lid_siz=(x->son[0]==nullptr)?0:x->son[0]->siz;
if(rk<=lid_siz)
{
auto temp=split_by_rk(x->son[0],rk);
x->son[0]=temp.second.second;
push_up(x);
return {temp.first,{temp.second.first,x}};
}
else if(rk<=lid_siz+x->cnt)
{
TreeNode* l;
TreeNode* r;
l=x->son[0];
r=x->son[1];
x->son[0]=x->son[1]=nullptr;
push_up(x);
return {l,{x,r}};
}
else
{
auto temp=split_by_rk(x->son[1],rk-lid_siz-x->cnt);
x->son[1]=temp.first;
push_up(x);
return {x,{temp.second.first,temp.second.second}};
}
}
TreeNode* merge(TreeNode* x,TreeNode* y)
{
if(x==nullptr) return y;
if(y==nullptr) return x;
if(x->rank<y->rank)
{
x->son[1]=merge(x->son[1],y);
push_up(x);
return x;
}
else
{
y->son[0]=merge(x,y->son[0]);
push_up(y);
return y;
}
}
void ins(int w)
{
auto temp1=split(rt,w);
auto temp2=split(temp1.first,w-1);
TreeNode* x;
if(temp2.second==nullptr)
{
x=new TreeNode;
x->son[0]=x->son[1]=nullptr;
x->siz=x->cnt=1;
x->val=w;
x->rank=rand();
}
else
{
temp2.second->cnt++;
push_up(temp2.second);
}
TreeNode* temp=merge(temp2.first,(temp2.second==nullptr)?x:temp2.second);
rt=merge(temp,temp1.second);
}
void del(int w)
{
auto temp1=split(rt,w);
auto temp2=split(temp1.first,w-1);
if(temp2.second->cnt>1)
{
temp2.second->cnt--;
push_up(temp2.second);
temp2.first=merge(temp2.first,temp2.second);
}
else
{
if(temp1.first==temp2.second)
{
temp1.first==nullptr;
}
delete temp2.second;
temp2.second=nullptr;
}
rt=merge(temp2.first,temp1.second);
}
int get_rank(TreeNode* x,int w)
{
auto temp=split(x,w-1);
int ret=((temp.first==nullptr)?0:temp.first->siz)+1;
x=merge(temp.first,temp.second);
return ret;
}
int get_num(TreeNode* x,int w)
{
auto temp=split_by_rk(x,w);
int ret=temp.second.first->val;
x=merge(temp.first,merge(temp.second.first,temp.second.second));
return ret;
}
int get_prev(int w)
{
auto temp=split(rt,w-1);
int ret=get_num(temp.first,temp.first->siz);
rt=merge(temp.first,temp.second);
return ret;
}
int get_next(int w)
{
auto temp=split(rt,w);
int ret=get_num(temp.second,1);;
rt=merge(temp.first,temp.second);
return ret;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
srand(time(NULL));
int m;
cin>>m;
while(m--)
{
int op;
cin>>op;
if(op==1)
{
int x;
cin>>x;
ins(x);
}
else if(op==2)
{
int x;
cin>>x;
del(x);
}
else if(op==3)
{
int x;
cin>>x;
cout<<get_rank(rt,x)<<"\n";
}
else if(op==4)
{
int x;
cin>>x;
cout<<get_num(rt,x)<<"\n";
}
else if(op==5)
{
int x;
cin>>x;
cout<<get_prev(x)<<"\n";
}
else
{
int x;
cin>>x;
cout<<get_next(x)<<"\n";
}
}
return 0;
}
cdq分治
const int N=100010;
int n,m,k,ans[N],f[N],val[N],sum[N<<1];
struct node
{
int idx,a,b,c,val;
} a[N],tmp[N];
bool operator <(node x,node y)
{
if(x.a!=y.a) return x.a<y.a;
else if(x.b!=y.b) return x.b<y.b;
return x.c<y.c;
}
map<node,int> mp;
void add(int x,int w)
{
for(int i=x;i<=k;i+=i&-i) sum[i]+=w;
}
int query(int x)
{
int ret=0;
for(int i=x;i;i-=i&-i) ret+=sum[i];
return ret;
}
void cdq(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
cdq(l,mid);cdq(mid+1,r);
int i=l,j=mid+1,idx=l;
while(i<=mid && j<=r)
{
if(a[i].b<=a[j].b)
{
add(a[i].c,a[i].val);
tmp[idx++]=a[i++];
}
else
{
ans[a[j].idx]+=query(a[j].c);
tmp[idx++]=a[j++];
}
}
while(i<=mid) add(a[i].c,a[i].val),tmp[idx++]=a[i++];
while(j<=r)
{
ans[a[j].idx]+=query(a[j].c);
tmp[idx++]=a[j++];
}
for(int f=l;f<=mid;f++) add(a[f].c,-a[f].val);
for(int i=l;i<=r;i++) a[i]=tmp[i];
}
signed main()
{
fin>>n>>k;
for(int i=1;i<=n;i++)
{
int A,B,C;fin>>A>>B>>C;
mp[{0,A,B,C,0}]++;
}
for(auto i:mp)
{
m++;
a[m]={m,i.first.a,i.first.b,i.first.c,i.second};
val[m]=i.second;
}
cdq(1,m);
for(int i=1;i<=m;i++) f[ans[i]+val[i]-1]+=val[i];
for(int i=0;i<n;i++) fout<<f[i]<<"\n";
return 0;
}
李超线段树
const int N=100010,inf=1e9;
const double eps=1e-10;
int idx[N<<2],tot;
struct node
{
double k,b;
double operator [](int x){return k*x+b;}
} f[N];
void upd(int id,int l,int r,int k)
{
if(!idx[id])
{
idx[id]=k;
return;
}
int mid=(l+r)>>1;
if(f[k][mid]-f[idx[id]][mid]>eps || (fabs(f[k][mid]-f[idx[id]][mid])<eps && k<idx[id])) swap(idx[id],k);
if(f[k][l]-f[idx[id]][l]>eps || (fabs(f[k][l]-f[idx[id]][l])<eps && k<idx[id])) upd(lid,l,mid,k);
if(f[k][r]-f[idx[id]][r]>eps || (fabs(f[k][r]-f[idx[id]][r])<eps && k<idx[id])) upd(rid,mid+1,r,k);
}
void add(int id,int l,int r,int L,int R,int k)
{
if(L<=l && r<=R)
{
upd(id,l,r,k);
return;
}
int mid=(l+r)>>1;
if(L<=mid) add(lid,l,mid,L,R,k);
if(R>mid) add(rid,mid+1,r,L,R,k);
}
int query(int id,int l,int r,int x)
{
if(l==r) return idx[id];
int mid=(l+r)>>1,ret=idx[id];
if(x<=mid)
{
int tmp=query(lid,l,mid,x);
if(f[tmp][x]-f[ret][x]>eps || (fabs(f[tmp][x]-f[ret][x])<eps && tmp<ret)) return tmp;
else return ret;
}
else
{
int tmp=query(rid,mid+1,r,x);
if(f[tmp][x]-f[ret][x]>eps || (fabs(f[tmp][x]-f[ret][x])<eps && tmp<ret)) return tmp;
else return ret;
}
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int q,lstans=0;fin>>q;
f[0].b=-inf;
while(q--)
{
int op;fin>>op;
if(op==1)
{
tot++;
int x,y,xx,yy;fin>>x>>y>>xx>>yy;
x=(x+lstans-1)%39989+1;xx=(xx+lstans-1)%39989+1;
y=(y+lstans-1)%1000000000+1;yy=(yy+lstans-1)%1000000000+1;
if(x>xx) swap(x,xx),swap(y,yy);
if(x==xx)
{
f[tot].k=0;f[tot].b=max(y,yy);
}
else
{
f[tot].k=1.0*(y-yy)/(x-xx);
f[tot].b=y-f[tot].k*x;
}
add(1,1,39989,x,xx,tot);
}
else
{
int x;fin>>x;x=(x+lstans-1)%39989+1;
fout<<(lstans=query(1,1,39989,x))<<"\n";
}
}
return 0;
}
线段树分裂
const int N=200010;
int idx[N],d[N],tot,son[N][26],fail[N],ans[N];
queue<int> q;
void get_fail()
{
for(int i=0;i<26;i++) if(son[0][i]) q.push(son[0][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;i++)
{
if(son[u][i])
{
fail[son[u][i]]=son[fail[u]][i];
d[fail[son[u][i]]]++;
q.push(son[u][i]);
}
else son[u][i]=son[fail[u]][i];
}
}
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++)
{
string t;cin>>t;
int now=0;
for(int j=0;j<(int)t.size();j++)
{
int c=t[j]-'a';
if(!son[now][c]) son[now][c]=++tot;
now=son[now][c];
}
idx[i]=now;
}
get_fail();
string s;cin>>s;
int now=0;
for(int i=0;i<(int)s.size();i++)
{
now=son[now][s[i]-'a'];
ans[now]++;
}
for(int i=0;i<=tot;i++) if(!d[i]) q.push(i);
while(!q.empty())
{
int u=q.front();q.pop();
int v=fail[u];ans[v]+=ans[u];
d[v]--;
if(!d[v]) q.push(v);
}
for(int i=1;i<=n;i++) cout<<ans[idx[i]]<<"\n";
return 0;
}
吉司机线段树
#define lid id<<1
#define rid id<<1|1
const int N=500010,inf=1e18;
int a[N];
struct TreeNode
{
int mxh,mx,cmx,sum,lazymx,lazycmx,lazymxh,lazycmxh,cntmx;
} t[N<<2];
void push_up(int id)
{
t[id].sum=t[lid].sum+t[rid].sum;
t[id].mx=max(t[lid].mx,t[rid].mx);
t[id].mxh=max(t[lid].mxh,t[rid].mxh);
if(t[lid].mx>t[rid].mx)
{
t[id].cntmx=t[lid].cntmx;
t[id].cmx=max(t[lid].cmx,t[rid].mx);
}
else if(t[lid].mx<t[rid].mx)
{
t[id].cntmx=t[rid].cntmx;
t[id].cmx=max(t[rid].cmx,t[lid].mx);
}
else
{
t[id].cntmx=t[lid].cntmx+t[rid].cntmx;
t[id].cmx=max(t[lid].cmx,t[rid].cmx);
}
}
void upd(int id,int l,int r,int valmx,int valcmx,int valmxh,int valcmxh)
{
t[id].sum+=valmx*t[id].cntmx+valcmx*(r-l+1-t[id].cntmx);
t[id].mxh=max(t[id].mxh,t[id].mx+valmxh);
t[id].mx+=valmx;
if(t[id].cmx!=-inf) t[id].cmx+=valcmx;
t[id].lazymxh=max(t[id].lazymxh,t[id].lazymx+valmxh);
t[id].lazymx+=valmx;
t[id].lazycmxh=max(t[id].lazycmxh,t[id].lazycmx+valcmxh);
t[id].lazycmx+=valcmx;
}
void push_down(int id,int l,int r)
{
int mx=max(t[lid].mx,t[rid].mx),mid=(l+r)>>1;
if(t[lid].mx==mx) upd(lid,l,mid,t[id].lazymx,t[id].lazycmx,t[id].lazymxh,t[id].lazycmxh);
else upd(lid,l,mid,t[id].lazycmx,t[id].lazycmx,t[id].lazycmxh,t[id].lazycmxh);
if(t[rid].mx==mx) upd(rid,mid+1,r,t[id].lazymx,t[id].lazycmx,t[id].lazymxh,t[id].lazycmxh);
else upd(rid,mid+1,r,t[id].lazycmx,t[id].lazycmx,t[id].lazycmxh,t[id].lazycmxh);
t[id].lazymx=t[id].lazymxh=t[id].lazycmx=t[id].lazycmxh=0;
}
void build(int id,int l,int r)
{
if(l==r)
{
t[id].sum=t[id].mx=t[id].mxh=a[l];
t[id].cmx=-inf;t[id].cntmx=1;
return;
}
int mid=(l+r)>>1;
build(lid,l,mid);build(rid,mid+1,r);
push_up(id);
}
void add(int id,int l,int r,int L,int R,int k)
{
if(L<=l&& r<=R)
{
upd(id,l,r,k,k,k,k);
return;
}
push_down(id,l,r);
int mid=(l+r)>>1;
if(L<=mid) add(lid,l,mid,L,R,k);
if(R>mid) add(rid,mid+1,r,L,R,k);
push_up(id);
}
void upd_min(int id,int l,int r,int L,int R,int k)
{
if(t[id].mx<=k) return;
if(L<=l && r<=R && t[id].cmx<k)
{
upd(id,l,r,k-t[id].mx,0,k-t[id].mx,0);
return;
}
push_down(id,l,r);
int mid=(l+r)>>1;
if(L<=mid) upd_min(lid,l,mid,L,R,k);
if(R>mid) upd_min(rid,mid+1,r,L,R,k);
push_up(id);
}
int query_sum(int id,int l,int r,int L,int R)
{
if(L<=l && r<=R) return t[id].sum;
push_down(id,l,r);
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query_sum(lid,l,mid,L,R);
if(R>mid) ret+=query_sum(rid,mid+1,r,L,R);
return ret;
}
int query_mx(int id,int l,int r,int L,int R)
{
if(L<=l && r<=R) return t[id].mx;
push_down(id,l,r);
int mid=(l+r)>>1,ret=-inf;
if(L<=mid) ret=max(ret,query_mx(lid,l,mid,L,R));
if(R>mid) ret=max(ret,query_mx(rid,mid+1,r,L,R));
return ret;
}
int query_mxh(int id,int l,int r,int L,int R)
{
if(L<=l && r<=R) return t[id].mxh;
push_down(id,l,r);
int mid=(l+r)>>1,ret=-inf;
if(L<=mid) ret=max(ret,query_mxh(lid,l,mid,L,R));
if(R>mid) ret=max(ret,query_mxh(rid,mid+1,r,L,R));
return ret;
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,q;fin>>n>>q;
for(int i=1;i<=n;i++) fin>>a[i];
build(1,1,n);
while(q--)
{
int op,l,r;fin>>op>>l>>r;
if(op==1)
{
int k;fin>>k;
add(1,1,n,l,r,k);
}
else if(op==2)
{
int k;fin>>k;
upd_min(1,1,n,l,r,k);
}
else if(op==3) fout<<query_sum(1,1,n,l,r)<<"\n";
else if(op==4) fout<<query_mx(1,1,n,l,r)<<"\n";
else fout<<query_mxh(1,1,n,l,r)<<"\n";
}
return 0;
}
图论
虚树
il bool cmp(int x,int y){return dfn[x]<dfn[y];}
il void build()
{
sort(a+1,a+1+m,cmp);
st[tp=1]=1;
for(int i=1;i<=m;i++)
{
if(a[i]==st[tp]) continue;
int lca=get_lca(a[i],st[tp]);
if(lca!=st[tp])
{
while(dfn[lca]<dfn[st[tp-1]])
{
e[st[tp-1]].push_back(st[tp]);
tp--;
}
if(lca==st[tp-1])
{
e[st[tp-1]].push_back(st[tp]);
tp--;
}
else
{
e[lca].push_back(st[tp]);
st[tp]=lca;
}
}
st[++tp]=a[i];
}
for(int i=1;i<tp;i++) e[st[i]].push_back(st[i+1]);
}
dinic最大流
const int N=210,M=5010,inf=1e18;
int n,m,S,T,ans,h[N],tot=1,cur[N],d[N];
queue<int> q;
struct edge
{
int to,nxt,w;
} e[M<<1];
il void add(int u,int v,int w)
{
tot++;
e[tot].to=v;e[tot].w=w;
e[tot].nxt=h[u];
h[u]=tot;
}
il bool bfs()
{
for(int i=1;i<=n;i++) cur[i]=h[i];
for(int i=1;i<=n;i++) d[i]=0;
d[S]=1;q.push(S);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].w && !d[v])
{
d[v]=d[u]+1;
q.push(v);
}
}
// cout<<u<<"\n";
}
return d[T]>0;
}
int dfs(int u,int val)
{
if(u==T) return val;
int w=0;
for(int& i=cur[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].w>0 && d[v]==d[u]+1)
{
int x=dfs(v,min(val-w,e[i].w));
if(x>0) w+=x,e[i].w-=x,e[i^1].w+=x;
if(w==val) return w;
}
// cout<<"\n";
}
return w;
}
il void Dinic()
{
ans=0;
while(bfs()) ans+=dfs(S,inf);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
fin>>n>>m>>S>>T;
for(int i=1;i<=m;i++)
{
int u,v,w;fin>>u>>v>>w;
add(u,v,w);add(v,u,0);
}
Dinic();
fout<<ans;
return 0;
}
zkw最小费用最大流
const int N=5010,M=50010,inf=1e9;
int h[N],tot=1,cur[N],ansf,ansc,n,m,S,T,vis[N];
int dis[N];
queue<int> q;
struct edge
{
int to,nxt,w,cost;
} e[M<<1];
il void add(int u,int v,int w,int cost)
{
tot++;
e[tot].nxt=h[u];e[tot].w=w;
e[tot].cost=cost;e[tot].to=v;
h[u]=tot;
}
il bool bfs()
{
for(int i=1;i<=n;i++) cur[i]=h[i];
for(int i=1;i<=n;i++) dis[i]=inf;
dis[S]=0;q.push(S);vis[S]=1;
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=0;
// fout<<u<<" "<<dis[u]<<"\n";
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].w && dis[v]>dis[u]+e[i].cost)
{
dis[v]=dis[u]+e[i].cost;
if(!vis[v]) vis[v]=1,q.push(v);
}
}
}
return dis[T]!=inf;
}
int dfs(int u,int val)
{
if(u==T) return val;
int w=0;vis[u]=1;
for(int& i=cur[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].w && dis[v]==dis[u]+e[i].cost && !vis[v])
{
int x=dfs(v,min(e[i].w,val-w));
if(x>0) ansc+=x*e[i].cost,w+=x,e[i].w-=x,e[i^1].w+=x;
if(w==val)
{
vis[u]=0;
return w;
}
}
}
vis[u]=0;
return w;
}
il void zkw()
{
while(bfs()) ansf+=dfs(S,inf);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
fin>>n>>m>>S>>T;
for(int i=1;i<=m;i++)
{
int u,v,w,cost;fin>>u>>v>>w>>cost;
add(u,v,w,cost);add(v,u,0,-cost);
}
zkw();
fout<<ansf<<" "<<ansc<<"\n";
return 0;
}
有源汇上下界最大流
const int N=1010,M=10010,inf=1e18;
int n,m,h[N],cur[N],tot=1,ansf,dis[N],d[N],SS,TT,S,T;
struct edge
{
int to,nxt,w;
} e[M<<2];
queue<int> q;
il void add(int u,int v,int w)
{
tot++;
e[tot].to=v;e[tot].w=w;
e[tot].nxt=h[u];h[u]=tot;
}
il void add_edge(int u,int v,int w)
{
add(u,v,w);add(v,u,0);
}
il bool bfs()
{
for(int i=1;i<=n;i++) cur[i]=h[i],dis[i]=0;
dis[SS]=1;q.push(SS);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].w && !dis[v])
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return dis[TT]>0;
}
int dfs(int u,int val)
{
if(u==TT) return val;
int w=0;
for(int& i=cur[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].w && dis[v]==dis[u]+1)
{
int x=dfs(v,min(e[i].w,val-w));
if(x) w+=x,e[i].w-=x,e[i^1].w+=x;
if(val==w) return w;
}
}
return w;
}
il void Dinic()
{
while(bfs()) ansf+=dfs(SS,inf);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
fin>>n>>m>>S>>T;
n+=2;SS=n-1,TT=n;
for(int i=1;i<=m;i++)
{
int u,v,l,r;fin>>u>>v>>l>>r;
d[v]+=l,d[u]-=l;
add_edge(u,v,r-l);
}
for(int i=1;i<=n;i++)
{
if(d[i]>0) add_edge(SS,i,d[i]);
else if(d[i]<0) add_edge(i,TT,-d[i]);
}
add_edge(T,S,inf);
Dinic();
for(int i=h[SS];i;i=e[i].nxt)
{
if(e[i].w!=0)
{
fout<<"N";
return 0;
}
}
ansf=e[tot].w;
SS=S,TT=T;
e[tot].w=e[tot-1].w=0;
Dinic();
fout<<ansf<<"\n";
return 0;
}
有源汇上下界最小流
const int N=1010,M=10010,inf=1e18;
int n,m,S,T,SS,TT,h[N],cur[N],tot=1,d[N],dis[N],ansf;
queue<int> q;
struct edge
{
int v,next,w;
} e[(N+M)<<1];
void add(int u,int v,int w)
{
e[++tot].next=h[u];
e[tot].v=v;e[tot].w=w;
h[u]=tot;
}
void add_edge(int u,int v,int w)
{
add(u,v,w);add(v,u,0);
}
bool bfs()
{
for(int i=1;i<=n;i++) cur[i]=h[i],dis[i]=0;
dis[SS]=1;q.push(SS);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(e[i].w && !dis[v])
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return dis[TT]>0;
}
int dfs(int u,int val)
{
if(u==TT) return val;
int w=0;
for(int& i=cur[u];i;i=e[i].next)
{
int v=e[i].v;
if(dis[v]==dis[u]+1 && e[i].w)
{
int x=dfs(v,min(e[i].w,val-w));
if(x>0) w+=x,e[i].w-=x,e[i^1].w+=x;
if(w==val) return w;
}
}
return w;
}
void dinic()
{
while(bfs())
{
ansf+=dfs(SS,inf);
// cout<<ansf<<"\n";
}
}
signed main()
{
fin>>n>>m>>S>>T;
n+=2;SS=n-1,TT=n;
for(int i=1;i<=m;i++)
{
int u,v,l,r;fin>>u>>v>>l>>r;
ansf+=l;
d[v]+=l;d[u]-=l;
add_edge(u,v,r-l);
}
for(int i=1;i<=n;i++)
{
if(d[i]>0) add_edge(SS,i,d[i]);
else if(d[i]<0) add_edge(i,TT,-d[i]);
}
add_edge(T,S,inf);
dinic();
for(int i=h[SS];i;i=e[i].next)
{
if(e[i].w!=0)
{
fout<<"N";
return 0;
}
}
int w=e[tot].w;
ansf=0;
SS=T,TT=S;
e[tot].w=e[tot-1].w=0;
dinic();
fout<<w-ansf;
return 0;
}
无源汇上下界可行流
const int N=1010,M=10010,inf=1e18;
int n,m,S,T,SS,TT,h[N],cur[N],ans[M],tot=1,d[N],dis[N],ansf;
queue<int> q;
struct edge
{
int v,next,w,idx;
} e[(N+M)<<1];
void add(int u,int v,int w,int idx)
{
e[++tot].next=h[u];
e[tot].idx=idx;
e[tot].v=v;e[tot].w=w;
h[u]=tot;
}
void add_edge(int u,int v,int w,int idx)
{
add(u,v,w,idx);add(v,u,0,idx);
}
bool bfs()
{
for(int i=1;i<=n;i++) cur[i]=h[i],dis[i]=0;
dis[SS]=1;q.push(SS);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(e[i].w && !dis[v])
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return dis[TT]>0;
}
int dfs(int u,int val)
{
if(u==TT) return val;
int w=0;
for(int& i=cur[u];i;i=e[i].next)
{
int v=e[i].v;
if(dis[v]==dis[u]+1 && e[i].w)
{
int x=dfs(v,min(e[i].w,val-w));
if(x>0) w+=x,e[i].w-=x,e[i^1].w+=x;
if(w==val) return w;
}
}
return w;
}
void dinic()
{
while(bfs())
{
ansf+=dfs(SS,inf);
// cout<<ansf<<"\n";
}
}
signed main()
{
fin>>n>>m;
n+=2;SS=n-1,TT=n;
for(int i=1;i<=m;i++)
{
int u,v,l,r;fin>>u>>v>>l>>r;
ans[i]=l;
d[v]+=l;d[u]-=l;
add_edge(u,v,r-l,i);
}
for(int i=1;i<=n;i++)
{
if(d[i]>0) add_edge(SS,i,d[i],m+1);
else if(d[i]<0) add_edge(i,TT,-d[i],m+1);
}
dinic();
for(int i=h[SS];i;i=e[i].next)
{
if(e[i].w!=0)
{
fout<<"No";
return 0;
}
}
for(int i=3;i<=tot;i+=2)
{
ans[e[i].idx]+=e[i].w;
}
fout<<"Yes\n";
for(int i=1;i<=m;i++) fout<<ans[i]<<"\n";
return 0;
}
LCT
#define il inline
const int N=100010,V=12;
struct node
{
int val,sum,fa,son[2],tag;
} t[N];
il bool Get(int x){return t[t[x].fa].son[1]==x;}
il bool is_root(int x){return t[t[x].fa].son[0]!=x && t[t[x].fa].son[1]!=x;}
il void push_up(int x)
{
t[x].sum=t[t[x].son[0]].sum^t[t[x].son[1]].sum^t[x].val;
}
il void lazy_reverse(int x)
{
swap(t[x].son[0],t[x].son[1]);
t[x].tag^=1;
}
il void push_down(int x)
{
if(t[x].tag)
{
lazy_reverse(t[x].son[0]);
lazy_reverse(t[x].son[1]);
t[x].tag=0;
}
}
il void update(int x)
{
if(!is_root(x)) update(t[x].fa);
push_down(x);
}
il void rotate(int x)
{
int y=t[x].fa,z=t[y].fa,r=Get(x);
if(!is_root(y)) t[z].son[t[z].son[1]==y]=x;
t[y].son[r]=t[x].son[!r],t[t[x].son[!r]].fa=y;
t[x].son[!r]=y,t[y].fa=x,t[x].fa=z;
push_up(y),push_up(x);
}
il void splay(int x)
{
update(x);
for(int fa;fa=t[x].fa,!is_root(x);rotate(x))
{
if(!is_root(fa)) rotate(Get(x)==Get(fa)?fa:x);
}
}
il int Access(int x)
{
int p;
for(p=0;x;p=x,x=t[x].fa)
{
splay(x),t[x].son[1]=p,push_up(x);
}
return p;
}
il void make_root(int x)
{
x=Access(x);
lazy_reverse(x);
}
il void Link(int u,int v)
{
make_root(u);
splay(u);
t[u].fa=v;
}
il void Split(int u,int v)
{
make_root(u);
Access(v);
splay(v);
}
il int Find(int u)
{
Access(u);
splay(u);
push_down(u);
while(t[u].son[0]) u=t[u].son[0],push_down(u);
splay(u);
return u;
}
il void Cut(int u,int v)
{
if(Find(u)!=Find(v)) return;
Split(u,v);
if(t[u].fa!=v || t[u].son[1]) return;
t[u].fa=t[v].son[0]=0;
}
signed main()
{
// freopen("b1.in","r",stdin);
// freopen("chj.out","w",stdout);
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++) cin>>t[i].val;
while(q--)
{
int op;cin>>op;
if(op==1)
{
int u,v;cin>>u>>v;
if(Find(u)!=Find(v)) Link(u,v);
}
if(op==2)
{
int u,v;cin>>u>>v;
Cut(u,v);
}
if(op==3)
{
int c,f;cin>>c>>f;
splay(c);
t[c].val=f;
push_up(c);
}
if(op==0)
{
int u,v;cin>>u>>v;
Split(u,v);
cout<<t[v].sum<<"\n";
}
}
return 0;
}
tarjan缩点
const int N=10010;
int dp[N],dfn[N],low[N],tot,scc[N],vis[N],st[N],tp,cnt,val[N],a[N],d[N];
queue<int> q;
vector<int> g[N],e[N];
void tarjan(int u)
{
low[u]=dfn[u]=++tot;
vis[u]=1;st[++tp]=u;
for(int v:g[u])
{
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
int v=0;cnt++;
while(v!=u)
{
v=st[tp--];
vis[v]=0;
scc[v]=cnt;
val[cnt]+=a[v];
}
}
}
signed main()
{
int n,m;fin>>n>>m;
for(int i=1;i<=n;i++) fin>>a[i];
for(int i=1;i<=m;i++)
{
int u,v;
fin>>u>>v;
g[u].push_back(v);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=n;i++)
{
for(int v:g[i])
{
if(scc[i]!=scc[v])
{
e[scc[i]].push_back(scc[v]);
d[scc[v]]++;
}
}
}
for(int i=1;i<=cnt;i++)
{
if(d[i]==0)
{
dp[i]=val[i];
q.push(i);
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int v:e[u])
{
d[v]--;
dp[v]=max(dp[v],dp[u]+val[v]);
if(d[v]==0) q.push(v);
}
}
int ans=0;
for(int i=1;i<=cnt;i++) ans=max(ans,dp[i]);
fout<<ans;
return 0;
}
tarjan求割点
int dfn[20010],low[20010],tot,ge[20010],cnt,ans[20010];
stack<int> st;
vector<int> g[20010];
void tarjan(int x,int fa)
{
dfn[x]=low[x]=++tot;
int son=0;
for(int i=0;i<g[x].size();i++)
{
int y=g[x][i];
if(!dfn[y])
{
son++;
tarjan(y,x);
low[x]=min(low[x],low[y]);
if(dfn[x]<=low[y]) ge[x]=true;
}
else if(y!=fa)
{
low[x]=min(low[x],dfn[y]);
}
}
if(fa==0 && son<2) ge[x]=false;
}
int main()
{
int n,m;
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i,0);
}
}
for(int i=1;i<=n;i++)
{
if(ge[i]) ans[++cnt]=i;
}
cout<<cnt<<"\n";
for(int i=1;i<=cnt;i++)
{
cout<<ans[i]<<" ";
}
return 0;
}
tarjan求点双
const int N=500010,M=2000010;
int h[N],tot,cnt,ttt,dfn[N],low[N],st[N],tp,vis[N];
struct node
{
int nxt,v;
} e[M<<1];
vector<int> b[N];
void add(int u,int v)
{
e[tot].nxt=h[u];
e[tot].v=v;
h[u]=tot++;
}
void tarjan(int u,int lst)
{
int flag=0;
dfn[u]=low[u]=++ttt;
st[++tp]=u;vis[u]=1;
for(int i=h[u];i!=-1;i=e[i].nxt)
{
int v=e[i].v;
if(i==(lst^1)) continue;
if(!dfn[v])
{
flag=1;
tarjan(v,i);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
cnt++;
while(st[tp+1]!=v)
{
vis[st[tp]]=0;
b[cnt].push_back(st[tp--]);
}
b[cnt].push_back(u);
}
}
else if(vis[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(lst==tot && flag==0)
{
tp--;cnt++;
b[cnt].push_back(u);
}
}
signed main()
{
int n,m;fin>>n>>m;
for(int i=1;i<=n;i++) h[i]=-1;
for(int i=1;i<=m;i++)
{
int u,v;fin>>u>>v;
add(u,v);add(v,u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i,tot);
}
fout<<cnt<<"\n";
for(int i=1;i<=cnt;i++)
{
fout<<b[i].size()<<" ";
for(int j:b[i]) fout<<j<<" ";
fout<<"\n";
}
return 0;
}
tarjan求边双
const int N=500010,M=2000010;
int h[N],tot,cnt,ttt,dfn[N],low[N],st[N],tp,vis[N];
struct node
{
int nxt,v;
} e[M<<1];
vector<int> b[N];
void add(int u,int v)
{
e[tot].nxt=h[u];
e[tot].v=v;
h[u]=tot++;
}
void tarjan(int u,int lst)
{
dfn[u]=low[u]=++ttt;
st[++tp]=u;vis[u]=1;
for(int i=h[u];i!=-1;i=e[i].nxt)
{
int v=e[i].v;
if(i==(lst^1)) continue;
if(!dfn[v])
{
tarjan(v,i);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
int v=0;
cnt++;
while(v!=u)
{
v=st[tp--];
vis[v]=0;
b[cnt].push_back(v);
}
}
}
signed main()
{
int n,m;fin>>n>>m;
for(int i=1;i<=n;i++) h[i]=-1;
for(int i=1;i<=m;i++)
{
int u,v;fin>>u>>v;
add(u,v);add(v,u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i,tot);
}
fout<<cnt<<"\n";
for(int i=1;i<=cnt;i++)
{
fout<<b[i].size()<<" ";
for(int j:b[i]) fout<<j<<" ";
fout<<"\n";
}
return 0;
}
spfa判负环
const int N=2010,inf=1e18;
struct node
{
int v,w;
};
vector<node> g[N];
queue<int> q;
int dis[N],n,m,cnt[N],vis[N];
bool spfa()
{
for(int i=1;i<=n;i++) dis[i]=inf,cnt[i]=vis[i]=0;
while(!q.empty()) q.pop();
q.push(1);vis[1]=1;dis[1]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(node i:g[u])
{
int v=i.v;
if(dis[v]>dis[u]+i.w)
{
dis[v]=dis[u]+i.w;
if(!vis[v])
{
if((++cnt[v])>=n) return 1;
q.push(v);vis[v]=1;
}
}
}
}
return 0;
}
signed main()
{
int t;
fin>>t;
while(t--)
{
fin>>n>>m;
for(int i=1;i<=n;i++) vector<node> ().swap(g[i]);
for(int i=1;i<=m;i++)
{
int u,v,w;
fin>>u>>v>>w;
g[u].push_back({v,w});
if(w>=0) g[v].push_back({u,w});
}
if(spfa()) fout<<"YES\n";
else fout<<"NO\n";
}
return 0;
}
点分治
struct node
{
int v,w;
};
vector<node> g[10010];
int ask[110],siz[10010],root,minn,del[10010];
int sum,ans[110],judge[10000010],d[10010];
int q[10010],dis[10010],cnt=0,n,m;
void get_root(int u,int fa)
{
int maxx=0;
siz[u]=1;
for(auto i:g[u])
{
int v=i.v;
if(del[v] || v==fa) continue;
get_root(v,u);
siz[u]+=siz[v];
maxx=max(maxx,siz[v]);
}
maxx=max(maxx,sum-siz[u]);
if(maxx<minn) minn=maxx,root=u;
}
void get_dis(int u,int fa)
{
dis[++cnt]=d[u];
for(node i:g[u])
{
int v=i.v;
if(v==fa || del[v]) continue;
d[v]=d[u]+i.w;
get_dis(v,u);
}
}
void calc(int u)
{
del[u]=judge[0]=1;
int p=0;
for(node i:g[u])
{
int v=i.v;
if(del[v]) continue;
d[v]=i.w;
cnt=0;
get_dis(v,u);
for(int j=1;j<=cnt;j++)
{
for(int k=1;k<=m;k++)
{
if(dis[j]<=ask[k])
{
ans[k]|=judge[ask[k]-dis[j]];
}
}
}
for(int j=1;j<=cnt;j++)
{
if(dis[j]>1e7) continue;
judge[dis[j]]=1;
q[++p]=dis[j];
}
}
for(int i=1;i<=p;i++) judge[q[i]]=0;
}
void devide(int u)
{
calc(u);
del[u]=1;
for(node i:g[u])
{
int v=i.v;
if(del[v]) continue;
sum=minn=siz[v];
get_root(v,0);
devide(root);
}
}
int main()
{
// freopen("1.in","r",stdin);
cin>>n>>m;
for(int i=1;i<n;i++)
{
int u,v,w;
cin>>u>>v>>w;
g[u].push_back({v,w});
g[v].push_back({u,w});
}
for(int i=1;i<=m;i++) cin>>ask[i];
sum=minn=n;
get_root(1,0);
get_root(root,0);
devide(root);
for(int i=1;i<=m;i++)
{
if(ans[i]==1) cout<<"AYE\n";
else cout<<"NAY\n";
}
return 0;
}
点分树
const int N=100010;
int son[N],top[N],d[N],siz[N],f[N],RT,sz,mn,rt,del[N],dfa[N],lstans,n,a[N],cnt=1,h[N];
struct edge
{
int to,nxt;
} e[N<<1];
void add_edge(int u,int v)
{
cnt++;
e[cnt].to=v;e[cnt].nxt=h[u];
h[u]=cnt;
}
struct Tree
{
int rt[N],tot;
struct node
{
int sum,lid,rid;
} t[N*300];
void push_up(int id)
{
t[id].sum=t[t[id].lid].sum+t[t[id].rid].sum;
}
void add(int& id,int l,int r,int x,int k)
{
if(!id) id=++tot;
if(l==r)
{
t[id].sum+=k;
return;
}
int mid=(l+r)>>1;
if(x<=mid) add(t[id].lid,l,mid,x,k);
else add(t[id].rid,mid+1,r,x,k);
push_up(id);
}
int query(int id,int l,int r,int L,int R)
{
if(L<=l && r<=R) return t[id].sum;
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query(t[id].lid,l,mid,L,R);
if(R>mid) ret+=query(t[id].rid,mid+1,r,L,R);
return ret;
}
} T1,T2;
il void get_son(int u,int fa)
{
f[u]=fa;d[u]=d[fa]+1;
siz[u]=1;
// cout<<u<<"\n";
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
get_son(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
il void get_top(int u,int t)
{
top[u]=t;
if(son[u]) get_top(son[u],t);
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==f[u] || v==son[u]) continue;
get_top(v,v);
}
}
il void get_root(int u,int fa)
{
siz[u]=1;
int mx=0;
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa || del[v]) continue;
get_root(v,u);
siz[u]+=siz[v];
mx=max(mx,siz[v]);
}
mx=max(mx,sz-siz[u]);
if(mx<mn) mn=mx,rt=u;
}
il int get_dis(int u,int v)
{
int ret=0;
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]]) swap(u,v);
ret+=d[u]-d[top[u]]+1;
u=f[top[u]];
}
if(d[u]<d[v]) swap(u,v);
ret+=d[u]-d[v];
return ret;
}
il void build(int u)
{
del[u]=1;
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(del[v]) continue;
mn=sz=siz[v];
get_root(v,0);
get_root(rt,0);
dfa[rt]=u;
build(rt);
}
}
il void add(int x,int k)
{
int now=x;
while(now)
{
T1.add(T1.rt[now],0,n,get_dis(now,x),k);
if(dfa[now]) T2.add(T2.rt[now],0,n,get_dis(dfa[now],x),k);
now=dfa[now];
}
}
il int query(int x,int y)
{
int now=x,ret=0;
while(now)
{
int d=get_dis(now,x);
if(d<=y) ret+=T1.query(T1.rt[now],0,n,0,y-d);
if(!dfa[now]) break;
d=get_dis(dfa[now],x);
if(d<=y) ret-=T2.query(T2.rt[now],0,n,0,y-d);
now=dfa[now];
}
return ret;
}
signed main()
{
// freopen("P6329_1.in","r",stdin);
// freopen("chj.out","w",stdout);
int m;fin>>n>>m;
for(int i=1;i<=n;i++) fin>>a[i];
for(int i=1;i<n;i++)
{
int u,v;fin>>u>>v;
add_edge(u,v);add_edge(v,u);
}
get_son(1,0);
get_top(1,1);
sz=mn=n;
get_root(1,0);get_root(rt,0);
build(rt);
for(int i=1;i<=n;i++) add(i,a[i]);
while(m--)
{
int op,x,y;fin>>op>>x>>y;x^=lstans;y^=lstans;
if(op==0) fout<<(lstans=query(x,y))<<"\n";
else add(x,y-a[x]),a[x]=y;
}
return 0;
}
最小割树
const int N=510,M=1510,inf=1e18;
int d[N],h[N],cur[N],tot,n,m,id[N],S,T,vis[N],tmp[N],ans;
int mn[N][10],f[N][10],Q,dep[N];
struct Node
{
int v,w;
};
vector<Node> g[N];
queue<int> q;
struct edge
{
int v,next,w;
} e[M<<2];
struct node
{
int u,v,w;
} E[M];
void add(int u,int v,int w)
{
e[tot].next=h[u];
e[tot].v=v;e[tot].w=w;
h[u]=tot++;
}
void add_edge(int u,int v,int w)
{
add(u,v,w);add(v,u,0);
}
bool bfs()
{
for(int i=1;i<=n;i++) d[i]=0;
d[S]=1;
q.push(S);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=h[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(e[i].w>0 && d[v]==0)
{
d[v]=d[u]+1;
q.push(v);
}
}
}
return d[T]>0;
}
int dfs(int u,int val)
{
if(u==T) return val;
for(int& i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(e[i].w>0 && d[v]==d[u]+1)
{
int w=dfs(v,min(val,e[i].w));
if(w>0)
{
e[i].w-=w;
e[i^1].w+=w;
return w;
}
}
}
return 0;
}
void Dinic()
{
for(int i=1;i<=n;i++) h[i]=-1;
tot=ans=0;
for(int i=1;i<=m;i++)
{
add_edge(E[i].u,E[i].v,E[i].w);
add_edge(E[i].v,E[i].u,E[i].w);
}
while(bfs())
{
for(int i=1;i<=n;i++) cur[i]=h[i];
while(int dd=dfs(S,inf)) ans+=dd;
}
}
void get_vis(int u)
{
if(vis[u]) return;
vis[u]=1;
for(int i=h[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(e[i].w>0 && !(i&1)) get_vis(v);
}
}
void build(int l,int r)
{
if(l==r) return;
S=id[l];T=id[l+1];
Dinic();
g[S].push_back({T,ans});
g[T].push_back({S,ans});
for(int i=1;i<=n;i++) vis[i]=0;
get_vis(S);
int cnt1=0,cnt2=0;
for(int i=l;i<=r;i++) tmp[i]=id[i];
for(int i=l;i<=r;i++)
{
if(vis[tmp[i]]==1) id[l+(++cnt1)-1]=tmp[i];
else id[r-(++cnt2)+1]=tmp[i];
}
build(l,l+cnt1-1);
build(r-cnt2+1,r);
}
void get_mn(int u,int fa)
{
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=1;i<=9;i++)
{
f[u][i]=f[f[u][i-1]][i-1];
mn[u][i]=min(mn[u][i-1],mn[f[u][i-1]][i-1]);
}
for(auto i:g[u])
{
int v=i.v;
if(v==fa) continue;
mn[v][0]=i.w;
get_mn(v,u);
}
}
int query_mn(int u,int v)
{
int ret=inf;
if(dep[u]<dep[v]) swap(u,v);
for(int i=9;i>=0;i--)
{
if(dep[f[u][i]]>=dep[v])
{
ret=min(ret,mn[u][i]);
u=f[u][i];
}
}
if(u==v) return ret;
for(int i=9;i>=0;i--)
{
if(f[u][i]!=f[v][i])
{
ret=min(ret,min(mn[u][i],mn[v][i]));
u=f[u][i],v=f[v][i];
}
}
ret=min(ret,min(mn[u][0],mn[v][0]));
return ret;
}
signed main()
{
fin>>n>>m;
n++;
for(int i=1;i<=m;i++)
{
fin>>E[i].u>>E[i].v>>E[i].w;
E[i].u++,E[i].v++;
}
for(int i=1;i<=n;i++) id[i]=i;
build(1,n);
get_mn(1,0);
fin>>Q;
while(Q--)
{
int u,v;fin>>u>>v;
u++,v++;
fout<<query_mn(u,v)<<"\n";
}
return 0;
}
树哈希
const int N=60,p=13331,mod=1e9+7;
vector<int> g[N];
int sz,mn,rt,rrt,siz[N],Hash[N],d[N],powp[N];
pair<int,int> f[N],val[N];
il void get_rt(int u,int fa)
{
siz[u]=1;
int mx=0;
for(int v:g[u])
{
if(v==fa) continue;
get_rt(v,u);
siz[u]+=siz[v];
mx=max(mx,siz[v]);
}
mx=max(mx,sz-siz[u]);
// fout<<u<<" "<<mx<<"\n";
if(mx<mn) rt=u,rrt=0,mn=mx;
else if(mx==mn) rrt=u;
}
il void get_hash(int u,int fa)
{
d[u]=d[fa]+1;siz[u]=1;
Hash[u]=d[u];
for(int v:g[u])
{
if(v==fa) continue;
get_hash(v,u);
}
int cnt=0;
for(int v:g[u])
{
if(v==fa) continue;
val[++cnt]={Hash[v],siz[v]};
}
sort(val+1,val+1+cnt);
for(int i=1;i<=cnt;i++) Hash[u]=(Hash[u]+1ll*powp[siz[u]]*val[i].first)%mod,siz[u]+=val[i].second;
// fout<<u<<" "<<Hash[u]<<"\n";
}
il void solve(int idx)
{
int n;fin>>n;
for(int i=1;i<=n;i++) g[i].clear();
for(int i=1;i<=n;i++)
{
int u;fin>>u;
if(u) g[u].push_back(i),g[i].push_back(u);
}
mn=sz=n;rt=rrt=0;
get_rt(1,0);
get_hash(rt,0);f[idx].first=Hash[rt];
if(rrt) get_hash(rrt,0);f[idx].second=Hash[rrt];
// fout<<"\n";
if(f[idx].first>f[idx].second) swap(f[idx].first,f[idx].second);
}
signed main()
{
powp[0]=1;
for(int i=1;i<=50;i++) powp[i]=1ll*powp[i-1]*p%mod;
int m;fin>>m;
for(int i=1;i<=m;i++) solve(i);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=i;j++)
{
if(f[i]==f[j])
{
fout<<j<<"\n";
break;
}
}
}
return 0;
}
串串
SAM
const int N=1000010;
int tot=1,lst=1,d[N<<1],idx[N];
struct node
{
int len,cnt,ch[26],fa;
} dian[N<<1];
queue<int> q;
int SAM_add(int p,int c)
{
int np=++tot;
dian[np].len=dian[p].len+1;
while(p && !dian[p].ch[c]) dian[p].ch[c]=np,p=dian[p].fa;
if(!p) dian[np].fa=1;
else
{
int q=dian[p].ch[c];
if(dian[q].len==dian[p].len+1) dian[np].fa=q;
else
{
int nq=++tot;dian[nq]=dian[q];
dian[nq].len=dian[p].len+1;
dian[np].fa=dian[q].fa=nq;
while(p && dian[p].ch[c]==q) dian[p].ch[c]=nq,p=dian[p].fa;
}
}
return np;
}
signed main()
{
// freopen("P3804_2.in","r",stdin);
// freopen("chj.out","w",stdout);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
string s;cin>>s;int n=s.size();s=" "+s;
for(int i=1;i<=n;i++) lst=SAM_add(lst,s[i]-'a'),idx[i]=lst;
for(int i=1;i<=n;i++) dian[idx[i]].cnt++;
for(int i=1;i<=tot;i++) d[dian[i].fa]++;
for(int i=1;i<=tot;i++) if(!d[i]) q.push(i);
while(!q.empty())
{
int u=q.front();q.pop();
int v=dian[u].fa;d[v]--;
dian[v].cnt+=dian[u].cnt;
if(!d[v]) q.push(v);
}
long long ans=0;
for(int i=1;i<=tot;i++)
{
if(dian[i].cnt!=1)
{
ans=max(ans,1ll*dian[i].cnt*dian[i].len);
}
}
cout<<ans;
return 0;
}
manacher
const int N=11000010;
int p[N],n;
string s;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>s;n=s.size();s=" "+s;
int idx=0,R=0,ans=0;
for(int i=1;i<=n;i++)
{
int k=(i>R)?1:min(R-i+1,p[idx*2-i]);
while(i-k>=1 && i+k<=n && s[i-k]==s[i+k]) k++;
p[i]=k;
if(i+k-1>R) R=i+k-1,idx=i;
ans=max(ans,p[i]*2-1);
}
idx=0,R=0;
for(int i=1;i<=n;i++)
{
int k=(i>R)?0:min(R-i,p[2*idx-i]);
while(i-k>=1 && i+k+1<=n && s[i-k]==s[i+k+1]) k++;
p[i]=k;
if(i+k>R) R=i+k,idx=i;
ans=max(ans,p[i]*2);
}
cout<<ans;
return 0;
}
SA
const int N=1000010;
string s;
int n,sa[N],rk[N<<1],id[N],oldrk[N<<1],cnt[N],ht[N];
void get_sa()
{
int m=127,p=0;
for(int i=1;i<=n;i++) cnt[rk[i]=s[i]]++;
for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
for(int w=1;w<n;w<<=1,m=p)
{
int tot=0;
for(int i=n-w+1;i<=n;i++) id[++tot]=i;
for(int i=1;i<=n;i++) if(sa[i]>w) id[++tot]=sa[i]-w;
for(int i=1;i<=m;i++) cnt[i]=0;
for(int i=1;i<=n;i++) cnt[rk[i]]++;
for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for(int i=n;i>=1;i--) sa[cnt[rk[id[i]]]--]=id[i];
p=0;
for(int i=1;i<=n;i++) oldrk[i]=rk[i];
for(int i=1;i<=n;i++)
{
if(oldrk[sa[i]]==oldrk[sa[i-1]] && oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) rk[sa[i]]=p;
else rk[sa[i]]=++p;
}
if(p==n) break;
}
}
il void get_ht()
{
for(int i=1,k=0;i<=len;i++)
{
if(rk[i]==1) continue;
if(k) k--;
int j=sa[rk[i]-1];
while(i+k<=len && j+k<=len && S[i+k]==S[j+k]) k++;
ht[rk[i]]=k;
}
for(int i=1;i<=len;i++) mn[0][i]=ht[i];
for(int i=1;(1<<i)<=len;i++)
{
for(int j=1;j+(1<<i)-1<=len;j++)
{
mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]);
}
}
}
il int lcp(int x,int y)
{
if(x<1 || x>n || y<1 || y>n) return 0;
if(x==y) return n-x+1;
if((x=rk[x])>(y=rk[y])) swap(x,y);
int k=__lg(y-(x++));
return min(mn[k][x],mn[k][y-(1<<k)+1]);
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>s;n=s.size();s=" "+s;
get_sa();
for(int i=1;i<=n;i++) cout<<sa[i]<<" ";
return 0;
}
AC自动机
const int N=200010;
int idx[N],d[N],tot,son[N][26],fail[N],ans[N];
queue<int> q;
void get_fail()
{
for(int i=0;i<26;i++) if(son[0][i]) q.push(son[0][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;i++)
{
if(son[u][i])
{
fail[son[u][i]]=son[fail[u]][i];
d[fail[son[u][i]]]++;
q.push(son[u][i]);
}
else son[u][i]=son[fail[u]][i];
}
}
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++)
{
string t;cin>>t;
int now=0;
for(int j=0;j<(int)t.size();j++)
{
int c=t[j]-'a';
if(!son[now][c]) son[now][c]=++tot;
now=son[now][c];
}
idx[i]=now;
}
get_fail();
string s;cin>>s;
int now=0;
for(int i=0;i<(int)s.size();i++)
{
now=son[now][s[i]-'a'];
ans[now]++;
}
for(int i=0;i<=tot;i++) if(!d[i]) q.push(i);
while(!q.empty())
{
int u=q.front();q.pop();
int v=fail[u];ans[v]+=ans[u];
d[v]--;
if(!d[v]) q.push(v);
}
for(int i=1;i<=n;i++) cout<<ans[idx[i]]<<"\n";
return 0;
}
PAM
const int N=500010;
string s;
int tot=1,n,lstans,lst=1;
struct PAM
{
int ch[26],fail,cnt,len;
} dian[N];
il void ins(int now,int idx)
{
int c=s[idx]-'a';
while(idx-dian[now].len-1<1 || s[idx]!=s[idx-dian[now].len-1]) now=dian[now].fail;
if(dian[now].ch[c])
{
lstans=dian[dian[now].ch[c]].cnt;
lst=dian[now].ch[c];
return;
}
tot++;
int tmp=dian[now].fail;
while(idx-dian[tmp].len-1<1 || s[idx]!=s[idx-dian[tmp].len-1]) tmp=dian[tmp].fail;
dian[tot].fail=dian[tmp].ch[c];
dian[tot].len=dian[now].len+2;
dian[tot].cnt=dian[dian[tot].fail].cnt+1;
lstans=dian[tot].cnt;lst=tot;
dian[now].ch[c]=tot;
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
dian[0].fail=1;dian[1].len=-1;
fin>>s;s=" "+s;
for(int i=1;i<(int)s.size();i++)
{
s[i]=(s[i]-97+lstans)%26+97;
ins(lst,i);
fout<<lstans<<" ";
}
return 0;
}
杂项
插头DP
const int N=200010,P=13331;
string vis[20];
struct HashMap
{
int h[P],nxt[N],tot;
int key[N],val[N];
void clear()
{
tot=0;
for(int i=0;i<P;i++) h[i]=0;
}
void add(int x,int k)
{
int w=x%P;
for(int i=h[w];i;i=nxt[i])
{
if(key[i]==x)
{
val[i]+=k;
return;
}
}
tot++;
key[tot]=x,val[tot]=k,nxt[tot]=h[w];
h[w]=tot;
}
} dp[2];
il int get_w(int x,int k)
{
return x>>((k-1)<<1)&3;
}
il int ch_w(int x,int k,int v)
{
return x^(get_w(x,k)<<((k-1)<<1))^(v<<((k-1)<<1));
}
il int get_L(int x,int k)
{
int sum=1;
for(int i=k;i>=1;i--)
{
int w=get_w(x,i);
if(w==2) sum++;
if(w==1) sum--;
if(sum==0) return i;
}
return -1;
}
il int get_R(int x,int k)
{
int sum=1;
for(int i=k;i<=13;i++)
{
int w=get_w(x,i);
if(w==1) sum++;
if(w==2) sum--;
if(sum==0) return i;
}
return -1;
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,m,ex=0,ey=0;fin>>n>>m;
for(int i=1;i<=n;i++)
{
fin>>vis[i];vis[i]=" "+vis[i];
for(int j=1;j<=m;j++)
{
if(vis[i][j]=='.') ex=i,ey=j;
}
}
int pre=0,now=1,ans=0;
dp[pre].add(0,1);
for(int i=1;i<=n;i++)
{
for(int j=0;j<m;j++)
{
for(int k=1;k<=dp[pre].tot;k++)
{
int s=dp[pre].key[k],val=dp[pre].val[k];
int x=get_w(s,j+1),y=get_w(s,j+2);
if(vis[i][j+1]=='*')
{
if(!x && !y) dp[now].add(s,val);
}
else
{
if(!x && !y) dp[now].add(ch_w(ch_w(s,j+1,1),j+2,2),val);
else if(!x || !y)
{
dp[now].add(s,val);
dp[now].add(ch_w(ch_w(s,j+1,y),j+2,x),val);
}
else
{
s=ch_w(ch_w(s,j+1,0),j+2,0);
if(x==1 && y==2)
{
if(i==ex && j+1==ey && !s) ans+=val;
}
else if(x==2 && y==1) dp[now].add(s,val);
else if(x==1 && y==1)
{
int idx=get_R(s,j+2);
// fout<<idx<<" "<<j+2<<"!!!\n";
if(idx!=-1) dp[now].add(ch_w(s,idx,1),val);
}
else
{
int idx=get_L(s,j+1);
// fout<<idx<<" "<<j+1<<"@@@\n";
if(idx!=-1) dp[now].add(ch_w(s,idx,2),val);
}
}
}
}
swap(pre,now);
dp[now].clear();
}
for(int k=1;k<=dp[pre].tot;k++)
{
int s=dp[pre].key[k],val=dp[pre].val[k];
if(get_w(s,m+1)==0) dp[now].add(s<<2,val);
}
swap(pre,now);
dp[now].clear();
}
fout<<ans<<"\n";
return 0;
}
笛卡尔树
const int N=10000010;
int son[N][2],a[N],st[N],tp,n,ansl,ansr;
void build()
{
for(int i=1;i<=n;i++)
{
int now=tp;
while(tp && a[st[tp]]>a[i]) tp--;
if(now!=tp) son[i][0]=st[tp+1];
if(tp) son[st[tp]][1]=i;
st[++tp]=i;
}
// for(int i=1;i<=n;i++) fout<<son[i][0]<<" "<<son[i][1]<<"\n";
}
signed main()
{
fin>>n;
for(int i=1;i<=n;i++) fin>>a[i];
build();
for(int i=1;i<=n;i++) ansl^=i*(son[i][0]+1),ansr^=i*(son[i][1]+1);
fout<<ansl<<" "<<ansr;
return 0;
}
各种反演
1.二项式反演
\[f(n)=\sum_{i=n}^m\binom{i}{n}g(i)\Longleftrightarrow g(n)=\sum_{i=n}^m(-1)^{i-n}\binom{i}{n}f(i)
\]
2.斯特林反演
\[f(n)=\sum_{i=n}^{m}\begin{Bmatrix}i\\n\end{Bmatrix}g(i)\Longleftrightarrow g(n)=\sum_{i=n}^m(-1)^{i-n}\begin{bmatrix}i\\n\end{bmatrix}f(i)
\]
第一/二类斯特林数有关
\[\begin{aligned}
&\begin{Bmatrix}n\\m\end{Bmatrix}=\begin{Bmatrix}n-1\\m-1\end{Bmatrix}+m\begin{Bmatrix}n-1\\m\end{Bmatrix}\\
&\begin{Bmatrix}n\\m\end{Bmatrix}=\sum_{i=0}^m\frac{(-1)^{m-i}i^n}{(m-i)!i!}\\
&\begin{bmatrix}n\\m\end{bmatrix}=\begin{bmatrix}n-1\\m-1\end{bmatrix}+(n-1)\begin{bmatrix}n-1\\m\end{bmatrix}
\end{aligned}
\]
上升、下降幂有关
\[\begin{aligned}
\binom{n}{k}k^{\underline{i}}=\binom{n-i}{k-i}n^{\underline{i}}
\end{aligned}
\]
幂的互化
\[\begin{aligned}
&x^{\overline{n}}\sum_{i=0}^n\begin{bmatrix}n\\i\end{bmatrix}x^i\\
&x^n=\sum_{i=0}^n\begin{Bmatrix}n\\i\end{Bmatrix}(-1)^{n-i}x^{\overline{i}}\\
&x^n=\sum_{i=0}^n\begin{Bmatrix}n\\i\end{Bmatrix}x^{\underline{i}}\\
&x^{\underline{n}}=\sum_{i=0}^n\begin{bmatrix}n\\i\end{bmatrix}(-1)^{n-i}x^i
\end{aligned}
\]
浙公网安备 33010602011771号