模板合集
神奇的模板...总之各种各样的模板整理...已经准备用我现在的码风重新打一遍了...
高精度
- 已重载运算符.没写FFT什么的...
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int B = 10;
const int W = 1;
struct Big{
vector<int> s;
void clear(){ s.clear(); }
Big(LL num=0){ *this=num; }
Big operator = (LL x){
clear();
do{ s.push_back(x%B),x/=B; }while(x);
return *this;
}
Big operator = (const string &str){
clear();
int x,len=(str.length()-1)/W+1,l=str.length();
for(int i=0;i<len;i++){
int tt=l-i*W,st=max(0,tt-W);
sscanf(str.substr(st,tt-st).c_str(),"%d",&x);
s.push_back(x);
}return *this;
}
};
istream& operator >> (istream & in,Big &a){
string s;
if(!(in>>s)) return in;
a=s;return in;
}
ostream& operator << (ostream &out,const Big &a){
cout<<a.s.back();
for(int i=a.s.size()-2;~i;i--){
cout.width(W),cout.fill('0'),cout<<a.s[i];
}return out;
}
bool operator < (const Big &a,const Big &b){
int la=a.s.size(),lb=b.s.size();
if(la<lb) return 1;if(la>lb) return 0;
for(int i=la-1;~i;i--){
if(a.s[i]<b.s[i]) return 1;
if(a.s[i]>b.s[i]) return 0;
}return 0;
}
bool operator <= (const Big &a,const Big &b){ return !(b<a); }
bool operator > (const Big &a,const Big &b){ return b<a; }
bool operator >= (const Big &a,const Big &b){ return !(a<b); }
bool operator == (const Big &a,const Big &b){ return !(a>b) && !(a<b); }
bool operator != (const Big &a,const Big &b){ return a>b || a<b ; }
Big operator + (const Big &a,const Big &b){
Big c;c.clear();
int lim=max(a.s.size(),b.s.size()),la=a.s.size(),lb=b.s.size(),i,g,x;
for(i=0,g=0;;i++){
if(g==0 && i>=lim) break;
x=g;if(i<la) x+=a.s[i];if(i<lb) x+=b.s[i];
c.s.push_back(x%B),g=x/B;
}i=c.s.size()-1;
while(c.s[i]==0 && i) c.s.pop_back(),i--;
return c;
}
Big operator - (const Big &a,const Big &b){
Big c;c.clear();
int i,g,x,la=a.s.size(),lb=b.s.size();
for(i=0,g=0;i<la;i++){
x=a.s[i]-g;
if(i<lb) x-=b.s[i];
if(x>=0) g=0;else g=1,x+=B;
c.s.push_back(x);
}i=c.s.size()-1;
while(c.s[i]==0 && i) c.s.pop_back(),i--;
return c;
}
Big operator * (const Big &a,const Big &b){
Big c;
int i,j,la=a.s.size(),lb=b.s.size(),lc=la+lb;
c.s.resize(lc,0);
for(i=0;i<la;i++) for(j=0;j<lb;j++) c.s[i+j]+=a.s[i]*b.s[j];
for(i=0;i<lc;i++) c.s[i+1]+=c.s[i]/B,c.s[i]%=B;
i=lc-1;while(c.s[i]==0 && i) c.s.pop_back(),i--;
return c;
}
Big operator / (const Big &a,const Big &b){
Big c,f=0;
int la=a.s.size(),i;
c.s.resize(la,0);
for(i=la-1;~i;i--){
f=f*B,f.s[0]=a.s[i];
int l=0,r=B,mid;
while(l<=r){
mid=(l+r)>>1;
if(mid*b > f) r=mid-1;
else l=mid+1;
}
f=f-r*b,c.s[i]=r;
// while(f>=b) f=f-b,c.s[i]++;
}i=la-1;while(c.s[i]==0 && i) c.s.pop_back(),i--;
return c;
}
Big operator % (const Big &a,const Big &b){
Big c=a-(a/b)*b;
return c;
}
Big operator ^ (Big &a,Big &b){
Big c=1;
for(;b!=0;b=b/2,a=a*a){
if(b.s[0] & 1) c=c*a;
}return c;
}
Big operator += (Big &a,const Big &b){ return a=a+b; }
Big operator -= (Big &a,const Big &b){ return a=a-b; }
Big operator *= (Big &a,const Big &b){ return a=a*b; }
Big operator /= (Big &a,const Big &b){ return a=a/b; }
Big operator %= (Big &a,const Big &b){ return a=a%b; }
int main(){
Big A,B;
cin>>A>>B;
cout<<A/B;
return 0;
}
- FFT \(O(nlogn)\)
#include <bits/stdc++.h>
using namespace std;
#define mpr make_pair
#define rr first
#define ii second
const int N = 5e5+50;
const int M = 25;
const double Pi = M_PI;
typedef pair< double,double > Complex;
Complex operator + (const Complex &a,const Complex &b) {
return mpr(a.rr+b.rr,a.ii+b.ii);
}
Complex operator - (const Complex &a,const Complex &b) {
return mpr(a.rr-b.rr,a.ii-b.ii);
}
Complex operator * (const Complex &a,const Complex &b) {
return mpr(a.rr*b.rr-a.ii*b.ii,a.rr*b.ii+a.ii*b.rr);
}
int n,m;
Complex a[N],b[N],c[N];
int ans[N],pow2[M];
void init(int x) {
pow2[0]=1;
for(int i=1;i<M;i++) pow2[i]=pow2[i-1]<<1;
for(m=0,n=1;n<x;n<<=1,m++);
n<<=1,m++;
}
void Rev(Complex a[]) {
for(int i=0,j=0;i<n;i++) {
if(i>j) swap(a[i],a[j]);
for(int k=n>>1;(j^=k)<k;k>>=1);
}
}
void DFT(Complex y[],int r) {
Rev(y);
for(int i=2;i<=n;i<<=1) {
Complex wi=mpr(cos(2.0*Pi/i),r*sin(2.0*Pi/i));
for(int k=0;k<n;k+=i) {
Complex w=mpr(1.0,0.0);
for(int j=k;j<k+i/2;j++) {
Complex t1=y[j],t2=w*y[j+i/2];
y[j]=t1+t2,y[j+i/2]=t1-t2;
w=w*wi;
}
}
}if(r==-1) for(int i=0;i<n;i++) y[i].rr/=n;
}
void FFT(Complex a[],Complex b[],Complex c[]) {
DFT(a,1),DFT(b,1);
for(int i=0;i<n;i++) c[i]=a[i]*b[i];
DFT(c,-1);
}
int main() {
string s1,s2;
cin>>s1>>s2;
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
init((int)max(s1.length(),s2.length()));
for(int i=0;i<(int)s1.length();i++) a[i]=mpr(s1[i]-'0',0);
for(int i=0;i<(int)s2.length();i++) b[i]=mpr(s2[i]-'0',0);
FFT(a,b,c);
for(int i=0;i<n;i++) ans[i]=c[i].rr+0.5;
for(int i=0;i<n;i++) ans[i+1]+=ans[i]/10,ans[i]%=10;
for(;!ans[n] && n;n--);
for(int i=n;~i;i--) putchar(ans[i]+'0');
return 0;
}
- FNT \(O(nlogn)\)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5+50;
const int p = (479 << 21) + 1;
const int g = 3;
int n;
LL a[N],b[N],c[N];
LL Pow(LL a,LL b,LL r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; }
void init(int x) {
for(n=1;n<x;n<<=1);n<<=1;
}
void Rev(LL a[]) {
for(int i=0,j=0;i<n;i++) {
if(i>j) swap(a[i],a[j]);
for(int k=n>>1;(j^=k)<k;k>>=1);
}
}
void FNT(LL y[],int r) {
Rev(y);
for(int i=2;i<=n;i<<=1) {
LL wi=Pow(g,(p-1)/i);
if(r==-1) wi=Pow(wi,p-2);
for(int k=0;k<n;k+=i) {
LL w=1;
for(int j=k;j<k+i/2;j++) {
LL t1=y[j],t2=(w*y[j+i/2])%p;
y[j]=(t1+t2)%p,y[j+i/2]=(t1-t2+p)%p;
w=w*wi%p;
}
}
}if(r==-1) {
LL inv=Pow(n,p-2);
for(int i=0;i<n;i++) y[i]=y[i]*inv%p;
}
}
void FFT(LL a[],LL b[],LL c[]) {
FNT(a,1),FNT(b,1);
for(int i=0;i<n;i++) c[i]=a[i]*b[i]%p;
FNT(c,-1);
}
int main() {
string s1,s2;
cin>>s1>>s2;
reverse(s1.begin(),s1.end());reverse(s2.begin(),s2.end());
for(int i=0;i<s1.length();i++) a[i]=s1[i]-'0';
for(int i=0;i<s2.length();i++) b[i]=s2[i]-'0';
init(max(s1.length(),s2.length()));
FFT(a,b,c);
for(int i=0;i<n;i++) c[i+1]=(c[i+1]+c[i]/10),c[i]=c[i]%10;
int p=n;for(;!c[p] && p>0;p--);
for(;~p;p--) printf("%d",c[p]);
return 0;
}
优化
- 读入优化
char *ps=(char *)malloc(20000000);
inline LL in(LL x=0){ for(;*ps>'9'||*ps<'0';ps++);
for(;*ps>='0'&&*ps<='9';ps++) x=(x<<3)+(x<<1)+*ps-'0';return x; }
fread(ps,1,20000000,stdin);
- 输出优化
inline void Out(LL x){
int l=0;char ch[65];
if(!x){ putchar('0');return; }
if(x<0) putchar('-'),x=-x;
while(x) ch[++l]=x%10+'0',x/=10;
for(int i=l;i;i--) putchar(ch[i]);
}
计算几何
- qwq
#include <bits/stdc++.h>
using namespace std;
namespace CG {
typedef long double LD;
const LD Pi = M_PI;
const LD PI = 2 * acos(0.0);
const LD eps = 1e-18;
const LD oo = 1e15;
#define sqr(x) ((x)*(x))
int dcmp(LD x) { return fabs(x)<=eps?0:(x<0?-1:1); }
struct Point {
LD x,y;
Point(LD _x=0,LD _y=0) :x(_x),y(_y) {}
void out() { cout<<"("<<x<<","<<y<<")"; }
};
typedef Point Vector;
int cmpx(const Point &a,const Point &b) { return dcmp(a.x-b.x)==0?a.y<b.y:a.x<b.x; }
Vector operator + (const Vector &a,const Vector &b) { return Vector(a.x+b.x,a.y+b.y); }
Vector operator - (const Vector &a,const Vector &b) { return Vector(a.x-b.x,a.y-b.y); }
Vector operator * (const Vector &a,LD b) { return Vector(a.x*b,a.y*b); }
Vector operator / (const Vector &a,LD b) { return Vector(a.x/b,a.y/b); }
bool operator == (const Point &a,const Point &b) { return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; }
LD Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; }
LD Cross(Vector a,Vector b) { return a.x*b.y-b.x*a.y; }
Vector Rot(Vector a,LD rd) { return Vector(a.x*cos(rd)-a.y*sin(rd),a.x*sin(rd)+a.y*cos(rd)); }
LD get_l(Vector a) { return sqrt(Dot(a,a)); }
LD get_d(Point a,Point b) { return sqrt(Dot(a-b,a-b)); }
LD get_a(Vector a) { return atan2(a.y,a.x); }
LD get_a(Vector a,Vector b) { return acos(Dot(a,b)/get_l(a)/get_l(b)); }
LD get_s(Point a,Point b,Point c) { return Cross(b-a,c-a)/2.0; }
struct Line {
Point p;
Vector v;
LD ang;
Line(Point _p=Point(),Vector _v=Vector()):p(_p),v(_v) { ang=get_a(v); }
LD get_l() { return sqrt(Dot(v,v)); }
Point get_p(LD t) { return p+v*t; }
Point get_s() { return p; }
Point get_t() { return p+v; }
int chkleft(Point P) { return dcmp(Cross(v,P-p))>0; }
};
int cmpa(const Line &a,const Line &b) { return dcmp(a.ang-b.ang)==-1; }
Point get_l_l(Line a,Line b) {
Vector u=a.p-b.p;
LD t=Cross(b.v,u)/Cross(a.v,b.v);
return a.get_p(t);
}
typedef Line Hp;
int get_h_h(vector<Hp> &hs,vector<Point> &pt) {
sort(hs.begin(),hs.end(),cmpa);
vector<Point> p(hs.size());
vector<Hp> q(hs.size());
int h,t;
q[h=t=0]=hs[0];
for(int i=1;i<(int)hs.size();i++) {
while(h<t && !hs[i].chkleft(p[t-1])) t--;
while(h<t && !hs[i].chkleft(p[h])) h++;
q[++t]=hs[i];
if(fabs(Cross(q[t].v,q[t-1].v))<eps) {
t--;
if(q[t].chkleft(hs[i].p)) q[t]=hs[i];
}
if(h<t) p[t-1]=get_l_l(q[t-1],q[t]);
}
while(h<t && !q[h].chkleft(p[t-1])) t--;
p[t]=get_l_l(q[h],q[t]);
for(int i=h;i<=t;i++) pt.push_back(p[i]);
return t-h+1;
}
struct Circle {
Point c;
LD r;
Point get_p(LD t) { return c+Point(cos(t)*r,sin(t)*r); }
LD get_rd(Point a,Point b) { return get_a(a-c,b-c); }
LD get_l(LD rd) { return r*rd; }
};
int get_c_l(Line L,Circle C,vector<Point> &res) {
LD a=L.v.x,b=L.p.x-C.c.x,c=L.v.y,d=L.p.y-C.c.y;
LD e=sqr(a)+sqr(c),f=2.0*(a*b+c*d),g=sqr(b)+sqr(d)-sqr(C.r);
LD dt=f*f-4*e*g;
if(dcmp(dt)<0) return 0;
if(dcmp(dt)==0) return res.push_back(L.get_p(-f/(2.0*e))),1;
LD x1=(-f-sqrt(dt))/(2.0*e),x2=(-f+sqrt(dt))/(2.0*e);
if(x1>x2) swap(x1,x2);
res.push_back(L.get_p(x1)),res.push_back(L.get_p(x2));return 2;
}
int get_c_c(Circle A,Circle B,vector<Point> &res) {
LD d=get_l(A.c-B.c);
if(dcmp(d)==0) return dcmp(A.r-B.r)==0?-1:0;
if(dcmp(A.r+B.r-d)<0) return 0;
if(dcmp(fabs(A.r-B.r)-d)>0) return 0;
LD a=get_a(B.c-A.c);
LD rd=acos((sqr(A.r)+sqr(d)-sqr(B.r))/(2.0*A.r*d));
Point p1,p2;
p1=A.get_p(a+rd),p2=A.get_p(a-rd);
res.push_back(p1);
if(p1==p2) return 1;
res.push_back(p2);
return 2;
}
/*---io---*/
ostream & operator << (ostream &os,const Point &p) { os<<p.x<<" "<<p.y;return os; }
istream & operator >> (istream &is,Point &p) { is>>p.x>>p.y;return is; }
ostream & operator << (ostream &os,const Circle &C) { os<<C.c<<" "<<C.r;return os; }
istream & operator >> (istream &is,Circle &C) { is>>C.c>>C.r;return is; }
};
int main() {
}
图论
- Tarjan-割点 \(O(m)\)
#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
const int N = 100005;
#define debug(a) cout<<#a<<"="<<a<<" "
int n,m,cnt,ans;
vector<int> g[N];
int b[N],out[N],du[N];
int dfsn[N],low[N];
inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
void Tarjan(int u,int fa){
dfsn[u]=low[u]=++cnt;int c=0;
for(int i=0,v;i<du[u];i++) if((v=g[u][i])!=fa){
if(!dfsn[v]){
Tarjan(v,u),low[u]=min(low[u],low[v]),c++;
if(fa>0&&dfsn[u]<=low[v]) b[u]=1;
}else low[u]=min(low[u],dfsn[v]);
}if(fa==0&&c>1) b[u]=1;
}
int main(){
n=in(),m=in();
for(int i=1,u,v;i<=m;i++) u=in(),v=in(),du[u]++,du[v]++,g[u].push_back(v),g[v].push_back(u);
for(int i=1;i<=n;i++) if(!dfsn[i]) Tarjan(i,0);
for(int i=1;i<=n;i++) if(b[i]) out[++ans]=i;
printf("%d\n",ans);
for(int i=1;i<=ans;i++) printf("%d ",out[i]);putchar('\n');
return 0;
}
- Tarjan-割边(桥) \(O(m)\)
#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
const int N = 100005;
#define mpr(a,b) make_pair(a,b)
int n,m,cnt,ans;
int iscut[N],e[N];
int dfsn[N],low[N];
struct Edge{ int fr,to,id; }edge[N];
vector<Edge> g[N];
inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
inline void Add_Edge(int u,int v,int id){
edge[id]=(Edge){ u,v,id };
g[u].push_back((Edge){ u,v,id });
g[v].push_back((Edge){ v,u,id });
}
void Tarjan(int u,int fa){
dfsn[u]=low[u]=++cnt;
for(int i=0,lim=g[u].size(),v;i<lim;i++) if((v=g[u][i].to)!=fa){
if(!dfsn[v]){
Tarjan(v,u);
if(low[v]>dfsn[u]) iscut[g[u][i].id]=1;
low[u]=min(low[u],low[v]);
}else low[u]=min(low[u],dfsn[v]);
}
}
int main(){
n=in(),m=in();
for(int i=1,u,v;i<=m;i++) u=in(),v=in(),Add_Edge(u,v,i);
for(int i=1;i<=n;i++) if(!dfsn[i]) Tarjan(i,0);
for(int i=1;i<=m;i++) if(iscut[i]) e[++ans]=i;
printf("%d\n",ans);
for(int i=1;i<=ans;i++) printf("%d\n",e[i]);
return 0;
}
- Tarjan-强连通分量+缩点. \(O(m)\)
#include<cstdio>
#include<stack>
#include<vector>
#include<iostream>
using namespace std;
const int N = 10005;
#define debug(a) cout<<#a<<"="<<a<<" "
#define ct cout<<endl
#define _ct cout<<"----------"<<endl
int n,m,cnt,bcnt;
int dfsn[N],low[N],ins[N],b[N],sz[N];
vector<int> g[N];
vector<int> h[N];
stack<int> stk;
struct Edge{ int fr,to; }edge[N*5];
inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
void Tarjan(int u){
dfsn[u]=low[u]=++cnt,ins[u]=1,stk.push(u);
for(int i=0,lim=g[u].size(),v;i<lim;i++){
v=g[u][i];
if(!dfsn[v]){ Tarjan(v),low[u]=min(low[u],low[v]); }
else if(ins[v]) low[u]=min(low[u],dfsn[v]);
}if(dfsn[u]==low[u]){
++bcnt;int v;
for(;;){ v=stk.top(),stk.pop(),ins[v]=0,b[v]=bcnt,sz[bcnt]++;if(u==v) break; }
}
}
int main(){
// freopen("in.in","r",stdin);
n=in(),m=in();
for(int i=1,u,v;i<=m;i++) u=in(),v=in(),g[u].push_back(v),edge[i]=(Edge){ u,v };
for(int i=1;i<=n;i++) if(!dfsn[i]) Tarjan(i);
// _ct;debug(bcnt),ct;
for(int i=1,u,v;i<=m;i++){
u=edge[i].fr,v=edge[i].to;
// debug(u),debug(v),ct;
// debug(b[u]),debug(b[v]),ct;
if(b[u]!=b[v]) h[b[u]].push_back(b[v]);
}return 0;
}
- LCA-倍增 \(O(nlogn+mlogn)\)
#include<cstdio>
#include<utility>
#include<vector>
#include<iostream>
using namespace std;
#define mpr make_pair
#define debug(a) cout<<#a<<"="<<a<<" "
typedef pair< int,int > pr;
const int N = 50005;
const int M = 31;
int n,m,k;
vector<pr> h[N];
int pow2[M],d[N];
int f[N][M],g[N][M];
inline int in(int x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
void DFS(int u,int fa,int dep){
d[u]=dep;
for(int i=0,v;i<h[u].size();i++) if((v=h[u][i].first)!=fa){
DFS(v,u,dep+1),f[v][0]=u,g[v][0]=h[u][i].second;
}
}
void work(){
pow2[0]=1;for(int i=1;i<M;i++) pow2[i]=pow2[i-1]<<1;
for(int j=1;j<M;j++) for(int i=0;i<n;i++) f[i][j]=f[f[i][j-1]][j-1],g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1];
}
int Dis(int u,int v){
if(d[u]<d[v]) swap(u,v);
int l=d[u]-d[v],res=0;
if(l) for(int i=0;i<M;i++) if(l&pow2[i]) res+=g[u][i],u=f[u][i];
if(u==v) return res;
for(int i=M-1;~i;--i){
if(f[u][i]!=f[v][i]) res+=g[u][i]+g[v][i],u=f[u][i],v=f[v][i];
}return g[u][0]+g[v][0]+res;
}
int main(){
n=in();
for(int i=1,u,v,w;i<n;i++) u=in(),v=in(),w=in(),h[u].push_back(mpr(v,w)),h[v].push_back(mpr(u,w));
DFS(0,0,1);
work();
for(k=in();k--;){
int u=in(),v=in();
printf("%d\n",Dis(u,v));
}return 0;
}
- LCA-ST表 \(O(nlogn+m)\)
#include<cstdio>
#include<cmath>
#include<cstring>
#include<utility>
#include<vector>
#include<iostream>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<" "
#define mpr make_pair
typedef pair< int,int > pr;
const int N = 200005;
const int M = 25;
int n,m,cnt;
vector< pr > g[N];
int pow2[M],dfs[N],d[N],val[N],pos[N],lg2[N];
int f[N][M];
inline int in(int x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
void DFS(int u,int fa,int dep,int value){
dfs[++m]=u,d[u]=dep,val[u]=value,pos[u]=m,f[m][0]=u;
for(int i=0,v;i<g[u].size();i++) if((v=g[u][i].first)!=fa) DFS(v,u,dep+1,value+g[u][i].second),dfs[++m]=u,f[m][0]=u;
}
void init(){
pow2[0]=1;for(int i=1;i<M;i++) pow2[i]=pow2[i-1]<<1;
lg2[0]=-1;for(int i=1;i<=m;i++) lg2[i]=lg2[i>>1]+1;
for(int j=1;j<M;j++) for(int i=1;i<=m;i++) if(i+pow2[j]-1<=m){
int u=f[i][j-1],v=f[i+pow2[j-1]][j-1];
if(d[u]<d[v]) f[i][j]=u;else f[i][j]=v;
}
}
int Dis(int u,int v,int lca=0){
if(pos[u]<pos[v]) swap(u,v);
int lg=lg2[pos[u]-pos[v]+1];
if(d[f[pos[v]][lg]]<d[f[pos[u]-pow2[lg]+1][lg]]) lca=f[pos[v]][lg];else lca=f[pos[u]-pow2[lg]+1][lg];
return val[u]+val[v]-2*val[lca];
}
int main(){
memset(d,0x3f,sizeof(d));
n=in();
for(int i=1,u,v,w;i<n;i++) u=in(),v=in(),w=in(),g[u].push_back(mpr(v,w)),g[v].push_back(mpr(u,w));
DFS(0,0,1,0),init();
for(int k=in(),u,v;k--;){
u=in(),v=in();
printf("%d\n",Dis(u,v));
}return 0;
}
- 网络流-ISAP \(O(V^{2}E)\)
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
const int INF = 0x7fffffff;
const int N = 505;
const int M = 805;
inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
struct NetWork{
int n,m,s,t;
struct Edge{ int fr,to,flow; }edge[M<<1];int cnte;
vector<int> g[N];int flow;
int num[N],cur[N],d[N],p[N];bool v[N];
void Add_Edge(int fr,int to,int fl){
edge[cnte++]=(Edge){ fr,to,fl },edge[cnte++]=(Edge){ to,fr,0 };
g[fr].push_back(cnte-2),g[to].push_back(cnte-1);
}
int Add_Flow(){
int a=INF;
for(int x=t;x!=s;x=edge[p[x]].fr) a=min(a,edge[p[x]].flow);
for(int x=t;x!=s;x=edge[p[x]].fr) edge[p[x]].flow-=a,edge[p[x]^1].flow+=a;
return a;
}
void BFS(){
for(int i=1;i<=n;i++) d[i]=n;
memset(v,0,sizeof(v));
queue<int> q;q.push(t),v[t]=1,d[t]=0;
for(int x;!q.empty();){
x=q.front(),q.pop();
for(int i=0,lim=g[x].size();i<lim;i++){
Edge &e=edge[g[x][i]];
Edge &u=edge[g[x][i]^1];
if(!v[e.to]&&u.flow) d[e.to]=d[x]+1,v[e.to]=1,q.push(e.to);
}
}
}
int ISAP(){
BFS();int flow=0;
memset(num,0,sizeof(num)),memset(cur,0,sizeof(cur));
for(int i=1;i<=n;i++) num[d[i]]++;
for(int x=s,ok;d[s]<n;){
if(x==t) flow+=Add_Flow(),x=s;ok=0;
for(int &i=cur[x],lim=g[x].size();i<lim;i++){
Edge &e=edge[g[x][i]];
if(e.flow&&d[x]==d[e.to]+1){
ok=1,p[e.to]=g[x][i],x=e.to;break;
}
}
if(!ok){
int tmp=n-1;
for(int i=0,lim=g[x].size();i<lim;i++) tmp=min(tmp,d[edge[g[x][i]].to]);
if(!(--num[d[x]])) break;num[d[x]=m+1]++,cur[x]=0;
if(x!=s) x=edge[p[x]].fr;
}
}return flow;
}
}isap;
int main(){ return 0; }
- 网络流-Dinic \(O(VE^{2})\)/二分图\(O(\sqrt{V}E)\)
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
#include<iostream>
using namespace std;
const int N = 505;
const int INF = 0x7fffffff;
int T,n,m,cnt,ans;
struct NetWork{
int n,m,s,t,flow;
struct Edge{ int fr,to,flow; };
vector<Edge> edge;vector<int> g[N];
int cur[N],d[N],p[N];
void Add_Edge(int fr,int to,int flow){
edge.push_back((Edge){ fr,to,flow });
edge.push_back((Edge){ to,fr,0 });
m=edge.size();
g[fr].push_back(m-2),g[to].push_back(m-1);
}
int BFS(){
memset(d,-1,sizeof(d));
queue<int> q;q.push(s),d[s]=0;
for(int x;!q.empty();){
x=q.front(),q.pop();
for(int i=0,lim=g[x].size();i<lim;i++){
Edge &e=edge[g[x][i]];
if(e.flow&&d[e.to]==-1) d[e.to]=d[x]+1,q.push(e.to);
}
}return d[t]!=-1;
}
int Dinic(){
flow=0;
for(int x,k;BFS();){
memset(cur,0,sizeof(cur));x=s,k=0;
for(int ok;;){
if(x==t){
int mine=-1,minf=0x7fffffff;
for(int i=0;i<k;i++) if(edge[p[i]].flow<minf) minf=edge[p[i]].flow,mine=i;
for(int i=0;i<k;i++) edge[p[i]].flow-=minf,edge[p[i]^1].flow+=minf;
x=edge[p[mine]].fr,k=mine,flow+=minf;
}ok=0;
for(int &i=cur[x],lim=g[x].size();i<lim;i++){
Edge &e=edge[g[x][i]];
if(e.flow>0&&d[x]+1==d[e.to]){
p[k++]=g[x][i],x=e.to,ok=1;break;
}
}
if(!ok){ if(!k) break;d[x]=-1,x=edge[p[--k]].fr; }
}
}return flow;
}
}dinic;
int main(){ return 0; }
- 最小生成树计数Matrix-Tree定理 \(O(n^3)\)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const double eps = 1e-8;
const int N = 105;
#define _0(x) ((x>0?x:-x)+eps>0)
int n,m;
int g[N][N],d[N];
double a[N][N];
double det(int n){
double res=1;int swpt=0;
for(int i=0,j,k;i<n;i++){
if(!_0(a[i][i])){
for(j=i+1;j<n;j++) if(_0(a[j][i])) break;
if(j>=n) return 0;
for(k=i;k<n;k++) swap(a[i][k],a[j][k]);
swpt++;
}res*=a[i][i];
// for(j=i+1;j<n;j++) a[i][j]/=a[i][i];
for(j=i+1;j<n;j++) for(k=i+1;k<n;k++) a[j][k]-=a[j][i]*a[i][k]/a[i][i];
if(swpt&1) return -res;return res;
}
inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
int main(){
for(int T=in();T--;){
n=in(),m=in();memset(a,0,sizeof(a)),memset(g,0,sizeof(g)),memset(d,0,sizeof(d));
for(int i=1,u,v;i<=m;i++) u=in()-1,v=in()-1,g[u][v]=g[v][u]=1,d[u]++,d[v]++;
for(int i=0;i<n;i++) a[i][i]=d[i];
for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(g[i][j]) a[i][j]-=1;
// for(int i=0;i<n;i++) for(int j=0;j<n;j++) printf("%.0lf%c",a[i][j]," \n"[j==n-1]);
printf("%.0lf\n",det(n-1));
// for(int i=0;i<n;i++) for(int j=0;j<n;j++) printf("%.0lf%c",a[i][j]," \n"[j==n-1]);
}return 0;
}
- 曼哈顿最小生成树 \(O(n logn)\)
#include<cstdio>
#include<cstring>
#include<vector>
#include<utility>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;
#define mpr(a,b) make_pair(a,b)
const int N = 50005;
int n,ans;
struct seat{ int x,y,id; }a[N],b[N];
bool operator < (const seat &a,const seat &b){ return a.x==b.x?a.y>b.y:a.x>b.x; }
int d[N<<1],id[N<<1],cnt,ys[N];
struct Edge{ int u,v,w; };
bool operator < (const Edge &a,const Edge &b){ return a.w>b.w; }
priority_queue<Edge> q;
int f[N];
inline int in(int x=0,char ch=getchar(),int v=1){
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();if(ch=='-') v=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*v; }
//int cmpx(const seat &a,const seat &b){ return a.x==b.x?a.x<b.x:a.y<b.y; }
//int cmpxy(const seat &a,const seat &b){ return a.y-a.x<b.y-b.x; }
inline int abs(int x){ return x<0?-x:x; }
int find(int x){ return f[x]==x?x:f[x]=find(f[x]); }
void Add_Edge(int u,int v){
int dis=abs(a[u].x-a[v].x)+abs(a[u].y-a[v].y);
q.push((Edge){ u,v,dis });
}
void Add(int x,int v,int pos){
for(;x;x-=x&-x) if(d[x]>v) d[x]=v,id[x]=pos;
}
int Query(int x){
int minv=0x7f7f7f7f,pos=-1;
for(;x<=cnt;x+=x&-x) if(d[x]<minv) minv=d[x],pos=id[x];
return pos;
}
void out(seat a){ cout<<a.x<<" "<<a.y<<" "<<a.id<<endl<<"***************\n"; }
void Build(){
/* Part1 x1>x0&&y1-x1>y0-x0 dis=(x1+y1)-(x0+y0) */
memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0;
for(int i=1;i<=n;i++) b[i]=a[i];
// for(int i=1;i<=n;i++) out(a[i]);
sort(b+1,b+n+1);
// for(int i=1;i<=n;i++) out(b[i]);
for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x;
sort(ys+1,ys+n+1);
cnt=unique(ys+1,ys+n+1)-ys-1;
// cout<<cnt<<endl;
// for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl;
for(int i=1;i<=n;i++){
int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys;
int pos=Query(x);
if(~pos) Add_Edge(b[i].id,pos);
// cout<<b[i].id<<"-->"<<pos<<endl;
Add(x,b[i].x+b[i].y,b[i].id);
}
/* Part2 swap(x,y) */
memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0;
for(int i=1;i<=n;i++) b[i].y=a[i].x,b[i].x=a[i].y,b[i].id=a[i].id;
sort(b+1,b+n+1);
// for(int i=1;i<=n;i++) out(b[i]);
for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x;
sort(ys+1,ys+n+1);
cnt=unique(ys+1,ys+n+1)-ys-1;
// cout<<cnt<<endl;
// for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl;
for(int i=1;i<=n;i++){
int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys;
int pos=Query(x);
if(~pos) Add_Edge(b[i].id,pos);
// cout<<b[i].id<<"-->"<<pos<<endl;
Add(x,b[i].x+b[i].y,b[i].id);
}
/* Part3 y=-y */
memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0;
for(int i=1;i<=n;i++) b[i]=a[i],b[i].y=-b[i].y;
sort(b+1,b+n+1);
// for(int i=1;i<=n;i++) out(b[i]);
for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x;
sort(ys+1,ys+n+1);
cnt=unique(ys+1,ys+n+1)-ys-1;
// cout<<cnt<<endl;
// for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl;
for(int i=1;i<=n;i++){
int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys;
int pos=Query(x);
if(~pos) Add_Edge(b[i].id,pos);
// cout<<b[i].id<<"-->"<<pos<<endl;
Add(x,b[i].x+b[i].y,b[i].id);
}
/* Part4 swap(x,y) y=-y */
memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0;
for(int i=1;i<=n;i++) b[i].x=-a[i].y,b[i].y=a[i].x,b[i].id=a[i].id;
sort(b+1,b+n+1);
// for(int i=1;i<=n;i++) out(b[i]);
for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x;
sort(ys+1,ys+n+1);
cnt=unique(ys+1,ys+n+1)-ys-1;
// cout<<cnt<<endl;
// for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl;
for(int i=1;i<=n;i++){
int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys;
int pos=Query(x);
if(~pos) Add_Edge(b[i].id,pos);
// cout<<b[i].id<<"-->"<<pos<<endl;
Add(x,b[i].x+b[i].y,b[i].id);
}
/* MST */
for(int i=1;i<=n;i++) f[i]=i;
for(int k=1;!q.empty();){
Edge e=q.top();q.pop();
int u=e.u,v=e.v;
int f1=find(u),f2=find(v);
if(f1!=f2) k++,f[f2]=f1,ans+=e.w;
if(k>=n) break;
}cout<<ans<<endl;
}
int main(){
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
n=in();for(int i=1;i<=n;i++) a[i].x=in(),a[i].y=in(),a[i].id=i;
Build();
return 0;
}
- 朱刘算法/最小树形图 \(O(nm)\)
#include <bits/stdc++.h>
using namespace std;
inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
const int N = 55;
const int M = N*N+50;
struct Edge { int fr,to;double v; };
Edge edge[M];
int n,m,rt;
int b[N];
double mic[N];
double miv[N];
int pre[N],vis[N],id[N];
void AddEdge(int fr,int to,double v) { edge[++m]=(Edge){ fr,to,v }; }
double Solve(int n) {
double res=0;
for(int cnt,tmp;;) {
for(int i=1;i<=n;i++) miv[i]=1e9,pre[i]=0;
for(int i=1;i<=m;i++) {
Edge &e=edge[i];
if(e.v<miv[e.to]) miv[e.to]=e.v,pre[e.to]=e.fr;
}
for(int i=1;i<=n;i++) if(pre[i]) res+=miv[i];
memset(vis,0,sizeof(vis));
memset(id,0,sizeof(id));
vis[0]=tmp=1,cnt=0;
for(int i=1;i<=n;i++) if(!vis[i]) {
++tmp;int u=i;
for(;!vis[u];u=pre[u]) vis[u]=tmp;
if(vis[u]==tmp) {
++cnt;
for(;!id[u];u=pre[u]) id[u]=cnt;
}
}
if(!cnt) break;
for(int i=1;i<=n;i++) if(!id[i]) id[i]=++cnt;
int mm=m;m=0;
for(int i=1;i<=mm;i++) {
Edge &e=edge[i];
if(id[e.fr]!=id[e.to]) AddEdge(id[e.fr],id[e.to],e.v-miv[e.to]);
}
n=cnt;
}return res;
}
int main() {
n=in(),rt=n+1;
for(int i=1;i<=n;i++) {
double x;scanf("%lf",&x);
mic[i]=x;
b[i]=in();
if(b[i]) AddEdge(rt,i,x);
}
for(int k=in();k--;) {
int x=in(),y=in();
double z;scanf("%lf",&z);
if(b[x] && b[y]) {
AddEdge(x,y,z);
mic[y]=min(mic[y],z);
}
}
double ans=Solve(n+1);
// cout<<ans<<endl;
// for(int i=1;i<=n;i++) cout<<mic[i]<<" ";cout<<endl;
for(int i=1;i<=n;i++) if(b[i]) ans+=(b[i]-1)*mic[i];
printf("%.2lf\n",ans);
return 0;
}
数学
- 快速幂 \(O(logn)\) 快速乘 \(O(1)\)
inline LL Mul(LL a,LL b,LL p){
if(p<=1000000000) return a*b%p;
return (a*b-(LL)(a/(long double)p*b+1e-3)*p+p)%p;
// for(;b;b>>=1,a=(a+a)%p) if(b&1) res=(res+a)%p;return res;
}
inline LL Pow(LL a,LL b,LL p,LL res=1){ for(;b;b>>=1,a=Mul(a,a,p)) if(b&1) res=Mul(res,a,p);return res; }
-
\(\varphi(n)\) \(O(\sqrt{n})\)
inline LL GetPhi(LL p){
LL res=p,m=sqrt(p)+0.5;
for(int i=2;i<=m;i++) if(p%i==0){
res=res/i*(i-1);
while(p%i==0) p/=i;
}
if(p>1) res=res/p*(p-1);return res;
}
- 线性筛 \(\mu\) \(O(n)\)
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
const int N = 1000005;
int mu[N],pr[N],cnt;
bool b[N];
void Pre(){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!b[i]) mu[i]=-1,pr[++cnt]=i;
for(int j=1;j<=cnt&&pr[j]*i<=N;j++){
b[i*pr[j]]=1;
if(i%pr[j]) mu[i*pr[j]]=-mu[i];
else break;
}
}
// for(int i=1;i<=10;i++) cout<<mu[i]<<" ";cout<<endl;
}
int main(){ Pre();return 0; }
- 矩阵乘法和矩阵快速幂 \(O(n^3) O(n^3 logn)\)
#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
typedef long long LL;
typedef vector<LL> Vec;
typedef vector<Vec> Mat;
const LL p = 10000000007LL;
Mat operator * (const Mat &A,const Mat &B){
Mat C(A.size(),Vec(B[0].size()));
for(int i=0;i<A.size();i++) for(int j=0;j<B[0].size();j++) for(int k=0;k<A[0].size();k++)
C[i][j]=(C[i][j]+A[i][k]*B[k][j])%p;
return C;
}
Mat operator ^ (Mat A,LL b){
Mat res(A.size(),Vec(A[0].size()));
for(int i=0;i<A.size();i++) for(int j=0;j<A[0].size();j++) res[i][j]=(i==j)?1:0;
for(;b;b>>=1,A=A*A) if(b&1) res=res*A;
return res;
}
int main(){ return 0; }
- 扩展欧几里得 \(O(logn)\)
LL Exgcd(LL a,LL b,LL &x,LL &y){
if(!b){ x=1,y=0;return a; }
LL r=Exgcd(b,a%b,x,y);LL t=x;
x=y,y=t-(a/b)*y;return r;
}
- 中国剩余定理 \(O(nlogn)\)
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
const int N = 1005;
int n;
LL m[N],a[N];
LL Exgcd(LL a,LL b,LL &x,LL &y){
if(!b){ x=1,y=0;return a; }
LL r=Exgcd(b,a%b,x,y);LL t=x;
x=y,y=t-(a/b)*y;return r;
}
LL Solve(){
LL M=m[1],MM,res=0,x,y;
for(int i=2;i<=n;i++) M*=m[i];
for(int i=1;i<=n;i++){
MM=M/m[i];
Exgcd(MM,m[i],x,y);
res=(res+MM*x*a[i])%M;
}return res;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>m[i]>>a[i];
Solve();
return 0;
}
- 求解模线性方程组 \(O(nlogn)\)
#include<cstdio>
#include<utility>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
#define mpr make_pair
const int N = 1005;
LL n,a1,a2,b1,b2;
pair< LL,LL > m[N];
inline LL in(LL x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
LL Exgcd(LL a,LL b,LL &x,LL &y){
if(!b){ x=1,y=0;return a; }
LL r=Exgcd(b,a%b,x,y);LL t=x;
x=y,y=t-(a/b)*y;return r;
}
int Solve(){
LL x,y,d=Exgcd(a1,a2,x,y);
if((b2-b1)%d) return 0;
Exgcd(a1/d,a2/d,x,y),x*=(b2-b1)/d,x=(x%(a2/d)+a2/d)%(a2/d);
b1=a1*x+b1,a1=a1/d*a2,b1=(b1%a1+a1)%a1;
return 1;
}
int main(){
n=in();
for(LL i=1,u,v;i<=n;i++) u=in(),v=in(),m[i]=mpr(u,v);
a1=m[1].first,b1=m[1].second;
for(int i=2;i<=n;i++){
a2=m[i].first,b2=m[i].second;
if(!Solve()) return puts("-1"),0;
}return printf("%lld\n",b1),0;
}
字符串
- 后缀数组 \(O(nlogn)\)
#include <bits/stdc++.h>
using namespace std;
const int N = 200050;
int n,m=26;
char s[N];
int a[N];
namespace SuffixArray {
int s1[N],s2[N],sa[N],rk[N],ht[N],c[N];
void get_sa(int a[],int n=::n,int m=::m) {
int *x=s1,*y=s2;
for(int i=1;i<=n;i++) c[x[i]=a[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i;--i) sa[c[a[i]]--]=i;
for(int k=1,p=0;k<n;k<<=1,p=0) {
for(int i=n-k+1;i<=n;i++) y[++p]=i;
for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;
for(int i=0;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) c[x[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i;--i) sa[c[x[y[i]]]--]=y[i];
swap(x,y);x[sa[1]]=p=1;
for(int i=2;i<=n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]] &&
y[sa[i]+k]==y[sa[i-1]+k])?p:++p;
if(p>=n) break;
m=p;
}
}
void get_ht(int a[],int n=::n) {
for(int i=1;i<=n;i++) rk[sa[i]]=i;
for(int i=1,k=0,j;i<=n;ht[rk[i++]]=k)
for(j=sa[rk[i]-1],k=k?k-1:k;a[i+k]==a[j+k];k++);
}
}
int main() {
scanf("%s",s+1),n=strlen(s+1);
for(int i=1;i<=n;i++) a[i]=s[i]-'a'+1;
using namespace SuffixArray;
get_sa(a);get_ht(a);
for(int i=1;i<=n;i++) printf("%d%c",sa[i]," \n"[i==n]);
// for(int i=1;i<=n;i++) cout<<rk[i]<<" ";cout<<endl;
for(int i=2;i<=n;i++) printf("%d%c",ht[i]," \n"[i==n]);
return 0;
}
- Manacher \(O(n)\) 寻找最长回文串
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N = 1000005;
int p[N];
char s[N];
char ch[N];
int Manacher(char s[]){
int l=strlen(s+1),mx=0,res=0,id=0;
// cout<<l<<endl;
memset(p,0,sizeof(p));
for(int i=1;i<=l;i++){
if(mx>i) p[i]=min(p[id*2-i],mx-i);
else p[i]=1;
while(s[i+p[i]]==s[i-p[i]]) p[i]++;
if(mx<i+p[i]) mx=i+p[i],id=i;
}
for(int i=1;i<=l;i++) res=max(p[i],res);
// for(int i=1;i<=l;i++) cout<<p[i]<<" ";cout<<endl;
return res-1;
}
int main(){
cin>>(s+1);ch[0]='$';ch[1]='#';
for(int i=1;i<=strlen(s+1);i++) ch[i*2]=s[i],ch[i*2+1]='#';
// cout<<(ch+1)<<endl;
cout<<Manacher(ch)<<endl;
return 0;
}
- 后缀自动机(SAM) \(O(n)\)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N = 250005;
struct State{
State *par,*go[26];
int val;
State(int _val):par(0),val(_val){ memset(go,0,sizeof(go)); }
}*rt,*lst;
void extend(int w){
State *p=lst,*np=new State(p->val+1);
while(p && p->go[w]==0) p->go[w]=np,p=p->par;
if(!p) np->par=rt;
else{
State *q=p->go[w];
if(q->val == p->val+1) np->par=q;
else{
State *nq=new State(p->val+1);
memcpy(nq->go,q->go,sizeof(q->go));
nq->par=q->par;
np->par=q->par=nq;
while(p && p->go[w]==q) p->go[w]=nq,p=p->par;
}
}lst=np;
}
int main(){ rt=new State(0),lst=rt; }
数据结构
- Treap \(O(n\log n)\)
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<(#a)<<"="<<a<<" "
#define lc(o) ch[o][0]
#define rc(o) ch[o][1]
#define uor(i,j,k) for(int i=j;i<=(int)k;i++)
#define uep(i,j,k) for(int i=j;i<(int)k;i++)
#define dor(i,j,k) for(int i=j;i>=(int)k;i--)
typedef long long ll;
typedef pair<int,int> pr;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
const int N = 100050;
const int M = 25;
const int oo = 0x3fffffff;
const ll OO = 1e18;
const ll p = 1000000007;
ll Pow(ll a,ll b,ll r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; }
ll Pow(ll a,ll b,ll p,ll r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; }
ll inv(ll x) { return Pow(x,p-2); }
void Add(ll &x,ll y) { x=(x+y%p)%p; }
void Sub(ll &x,ll y) { x=(x-y%p+p)%p; }
void Mul(ll &x,ll y) { x=x*(y%p)%p; }
int chkmax(ll &x,ll y) { return x<y?x=y,1:0; }
int chkmin(ll &x,ll y) { return x>y?x=y,1:0; }
inline ll in(ll x=0,char ch=getchar(),int v=1) {
while(ch>'9' || ch<'0') v=ch=='-'?-1:v,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x*v;
}
/*end*/
namespace Treap {
int cp,rt;
int sz[N],ss[N],ch[N][2],f[N],rv[N];
int val[N];
int Newnode(int v) {
++cp,ss[cp]=sz[cp]=1,f[cp]=lc(cp)=rc(cp)=0,val[cp]=v,rv[cp]=rand();
return cp;
}
void init() { rt=0,rv[0]=-oo; }
void Update(int o) { sz[o]=sz[lc(o)]+sz[rc(o)]+ss[o]; }
void Rot(int &o,int d) {
int t=ch[o][d];ch[o][d]=ch[t][d^1],ch[t][d^1]=o,Update(o),Update(t),o=t;
}
void insert(int &o,int v) {
if(!o) { o=Newnode(v);return; }
if(val[o]==v) { ss[o]++,Update(o);return; }
int d=v>val[o];
insert(ch[o][d],v);
if(rv[ch[o][d]]>rv[o]) Rot(o,d);
else Update(o);
}
void earse(int &o,int v) {
if(val[o]==v) {
if(ss[o]>1) { ss[o]--,Update(o);return; }
int d=rv[lc(o)]<rv[rc(o)];
if(!ch[o][d]) { o=0;return; }
Rot(o,d),earse(ch[o][d^1],v);
}else earse(ch[o][v>val[o]],v);
Update(o);
}
int rk(int o,int v) {
if(val[o]<v) return sz[lc(o)]+ss[o]+rk(rc(o),v);
else if(val[o]>v) return rk(lc(o),v);
else return sz[lc(o)];
}
int kth(int o,int k) {
if(sz[lc(o)]>=k) return kth(lc(o),k);
else if(sz[lc(o)]+ss[o]<k) return kth(rc(o),k-sz[lc(o)]-ss[o]);
else return val[o];
}
int pre(int o,int v) {
if(!o) return -oo;
if(val[o]>=v) return pre(lc(o),v);
else return max(val[o],pre(rc(o),v));
}
int nxt(int o,int v) {
if(!o) return oo;
if(val[o]<=v) return nxt(rc(o),v);
else return min(val[o],nxt(lc(o),v));
}
void insert(int v) { insert(rt,v); }
void earse(int v) { earse(rt,v); }
int rk(int v) { return rk(rt,v); }
int kth(int k) { return kth(rt,k); }
int pre(int v) { return pre(rt,v); }
int nxt(int v) { return nxt(rt,v); }
};
int main() {
Treap::init();
for(int T=in();T--;) {
int opt=in(),x=in();
switch(opt) {
case 1:Treap::insert(x);break;
case 2:Treap::earse(x);break;
case 3:printf("%d\n",Treap::rk(x)+1);break;
case 4:printf("%d\n",Treap::kth(x));break;
case 5:printf("%d\n",Treap::pre(x));break;
case 6:printf("%d\n",Treap::nxt(x));break;
}
}
return 0;
}
- Splay \(O(n\log n)\)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200050;
inline LL in(LL x=0,char ch=getchar(),int v=1) {
while(ch>'9' || ch<'0') v=ch=='-'?-1:v,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x*v;
}
int n,q,nw;
LL a[N];
struct SplayTree {
#define lc(o) ch[o][0]
#define rc(o) ch[o][1]
#define mid ((l+r)>>1)
int cp,rt;
LL sum[N],v[N],d[N],rev[N],sz[N],f[N],ch[N][2];
int NewNode() {
++cp;
sum[cp]=v[cp]=d[cp]=rev[cp]=lc(cp)=rc(cp)=0;
sz[cp]=1;
return cp;
}
void Update(int o) {
if(!o) return;
sz[o]=sz[lc(o)]+sz[rc(o)]+1;
sum[o]=sum[lc(o)]+sum[rc(o)]+v[o]+d[o]*sz[o];
}
void Push(int o) {
if(!o) return;
Push(f[o]);
if(rev[o]) {
swap(lc(o),rc(o));
if(lc(o)) rev[lc(o)]^=1;
if(rc(o)) rev[rc(o)]^=1;
rev[o]=0;
}
if(d[o]) {
if(lc(o)) d[lc(o)]+=d[o];
if(rc(o)) d[rc(o)]+=d[o];
v[o]+=d[o],d[o]=0;
}Update(lc(o)),Update(rc(o)),Update(o);
}
void Pushdown(int o) {
if(!o) return;
if(rev[o]) {
swap(lc(o),rc(o));
if(lc(o)) rev[lc(o)]^=1;
if(rc(o)) rev[rc(o)]^=1;
rev[o]=0;
}
if(d[o]) {
if(lc(o)) d[lc(o)]+=d[o];
if(rc(o)) d[rc(o)]+=d[o];
v[o]+=d[o],d[o]=0;
}Update(lc(o)),Update(rc(o)),Update(o);
}
int Build(int l,int r) {
if(l>r){ return 0; }
int o=NewNode();
lc(o)=Build(l,mid-1);
v[o]=a[nw++];
rc(o)=Build(mid+1,r);
if(lc(o)) f[lc(o)]=o;
if(rc(o)) f[rc(o)]=o;
Update(o);
return o;
}
void Build(int n) {
rt=Build(1,n+2);
}
void Rot(int o) {
int p=f[o],k=f[p],r=rc(p)==o;
// Pushdown(k),Pushdown(p),Pushdown(o);
if(k) ch[k][rc(k)==p]=o;
f[p]=o,f[ch[o][r^1]]=p,f[o]=k;
ch[p][r]=ch[o][r^1],ch[o][r^1]=p;
Update(p),Update(o),Update(k);
}
void Splay(int o,int ff) {
Push(o);
for(;f[o]!=ff;) {
int p=f[o],k=f[p];
if(k!=ff) Rot((rc(k)==p)==(rc(p)==o)?p:o);
Rot(o);
}
Update(o);
if(!ff) rt=o;
}
int Kth(int o,int k) {
Pushdown(o);
if(sz[lc(o)]>=k) return Kth(lc(o),k);
else if(sz[lc(o)]+1==k) return o;
else return Kth(rc(o),k-sz[lc(o)]-1);
}
LL Kthw(int o,int k) {
Pushdown(o);
if(sz[lc(o)]>=k) return Kthw(lc(o),k)+d[o];
else if(sz[lc(o)]+1==k) return v[o]+d[o];
else return Kthw(rc(o),k-sz[lc(o)]-1)+d[o];
}
LL Kthw(int k) { return Kthw(rt,k+1); }
void Add(int l,int r,LL w) {
l++,r++;
int L=Kth(rt,l-1),R=Kth(rt,r+1);
Splay(L,0),Splay(R,L);
d[lc(R)]+=w;
Update(lc(R)),Update(R),Update(L);
}
void Insert(int x,LL w) {
x++;
int L=Kth(rt,x),R=Kth(rt,x+1);
Splay(L,0),Splay(R,L);
int np=NewNode();lc(R)=np,v[np]=w,f[np]=R;
Update(np),Update(R),Update(L);
}
void Del(int l,int r) {
l++,r++;
int L=Kth(rt,l-1),R=Kth(rt,r+1);
Splay(L,0),Splay(R,L);
lc(R)=0,Update(R),Update(L);
}
LL Qur(int l,int r) {
l++,r++;
int L=Kth(rt,l-1),R=Kth(rt,r+1);
Splay(L,0),Splay(R,L);
return sum[lc(R)];
}
void Rev(int l,int r) {
l++,r++;
int L=Kth(rt,l-1),R=Kth(rt,r+1);
Splay(L,0),Splay(R,L);
rev[lc(R)]^=1;
}
}py;
int main() {
n=in();
for(int i=1;i<=n;i++) a[i]=in();
py.Build(n);
char opt[20];
int l,r,k,x,v;
for(q=in();q--;) {
scanf("%s",opt);
if(opt[0]=='A') l=in(),r=in(),v=in(),py.Add(l,r,v);
if(opt[0]=='I') x=in(),v=in(),py.Insert(x,v);
if(opt[0]=='D') l=in(),r=in(),py.Del(l,r);
if(opt[0]=='Q') l=in(),r=in(),printf("%lld\n",py.Qur(l,r));
if(opt[0]=='K') k=in(),printf("%lld\n",py.Kthw(k));
if(opt[0]=='R') l=in(),r=in(),py.Rev(l,r);
}
return 0;
}

浙公网安备 33010602011771号