• SDOI2019 省选前模板整理


    代码不能折叠,不过就这样吧。有目录也还好。
    wdm好多。。
    可能要下辈子才能全填上✔了。✘✘✘
    Update:模板不复习,考场两行泪。
    我要是复习MillerRabin和快速乘就多十八分了啊TAT
    不过感谢复习了可持久化Trie。


    计算几何✔

    最近才写了,过了过了。虽然应该忘得差不多了。
    旋转卡壳:经常要找和当前直线平行的直线切在哪里,注意用底相同,平行线之间高也相同,以及叉积有正负的性质,求叉积。


    DP

    斜率优化✔

    将DP式子写成(y_j=kx_j+b)的形式,其中(k)是与(i)有关的系数,(b)是要求的(f_i)(i)的其他项。

    四边形不等式✔

    (f)满足四边形不等式,则决策单调,有(P[i][j-1]leq P[i][j]leq P[i+1][j])(P[i-1][j]leq P[i][j]leq P[i][j+1]),可根据需要使用。
    具体看这里
    实际上更大的用处是水过某些DP题...

    轮廓线DP✘

    nmd这东西根本写不出来的啊。


    各种分治

    CDQ分治✔

    //6196KB	688MS(308ms	5560KB)
    //https://www.cnblogs.com/SovietPower/p/8574905.html
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    #define MAXIN 300000
    //#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    typedef long long LL;
    const int N=1e5+5,M=2e5+5;
    
    int Ans[N];
    char IN[MAXIN],*SS=IN,*TT=IN;
    struct Node
    {
    	int x,y,z,cnt,ans;
    	bool operator <(const Node &a)const
    	{
    		return x==a.x?(y==a.y?z<a.z:y<a.y):x<a.x;
    	}
    	bool operator !=(const Node &a)const
    	{
    		return x!=a.x||y!=a.y||z!=a.z;
    	}
    }q[N],tmp[N];
    struct BIT
    {
    	int n,t[M];//M!
    	#define lb(x) (x&-x)
    	inline void Add(int p,int v)
    	{
    		for(; p<=n; p+=lb(p)) t[p]+=v;
    	}
    	inline int Query(int p)
    	{
    		int res=0;
    		for(; p; p^=lb(p)) res+=t[p];
    		return res;
    	}
    	inline void Clear(int p)
    	{
    		for(; p<=n&&t[p]; p+=lb(p)) t[p]=0;
    	}
    }T;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now;
    }
    void CDQ(int l,int r)
    {
    	if(l<r)
    	{
    		int m=l+r>>1; CDQ(l,m), CDQ(m+1,r);
    		int p1=l,p2=m+1,p=l;
    		while(p1<=m&&p2<=r)
    		{
    			if(q[p1].y<=q[p2].y) T.Add(q[p1].z,q[p1].cnt), tmp[p++]=q[p1++];//q[p1].cnt!
    			else q[p2].ans+=T.Query(q[p2].z), tmp[p++]=q[p2++];
    		}
    		while(p2<=r) q[p2].ans+=T.Query(q[p2].z), tmp[p++]=q[p2++];
    		for(int i=l; i<p1; ++i) T.Clear(q[i].z);//<p1
    		while(p1<=m) tmp[p++]=q[p1++];
    		for(int i=l; i<=r; ++i) q[i]=tmp[i];
    	}
    }
    
    int main()
    {
    	int n=read(); T.n=read();
    	for(int i=1; i<=n; ++i) q[i]=(Node){read(),read(),read(),1,0};//cnt不能是0啊= = 
    	std::sort(q+1,q+1+n); int cnt=1;
    	for(int i=2; i<=n; ++i)
    		if(q[i]!=q[i-1]) q[++cnt]=q[i];
    		else ++q[cnt].cnt;
    	CDQ(1,cnt);
    	for(int i=1; i<=cnt; ++i) Ans[q[i].ans+q[i].cnt-1]+=q[i].cnt;
    	for(int i=0; i<n; ++i) printf("%d
    ",Ans[i]);
    
    	return 0;
    }
    

    点分治✔

    过。

    整体二分✔

    //2740kb	132ms
    //https://www.cnblogs.com/SovietPower/p/9231606.html
    //原数列的值,要在树状数组上减掉啊。
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    //#define gc() getchar()
    #define MAXIN 400000
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    typedef long long LL;
    const int N=1e5+5,M=N*3;
    
    int A[N],Ans[N];
    char IN[MAXIN],*SS=IN,*TT=IN;
    struct Operation
    {
    	int l,r,k,id;//id=0:A[l]=r 变化量为k 
    }q[M];
    struct BIT
    {
    	int n,t[N];
    	#define lb(x) (x&-x)
    	inline void Add(int p,int v)
    	{
    		for(; p<=n; p+=lb(p)) t[p]+=v;
    	}
    	inline int Query(int p)
    	{
    		int res=0;
    		for(; p; p^=lb(p)) res+=t[p];
    		return res;
    	}
    	inline void Clear(int p)
    	{
    		for(; p<=n&&t[p]; p+=lb(p)) t[p]=0;
    	}
    }T;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now;
    }
    inline char GetOpt()
    {
    	register char c=gc(); while(c!='Q'&&c!='C') c=gc();
    	return c;
    }
    void Solve(int l,int r,int h,int t)
    {
    	static Operation q1[M],q2[M];
    	if(h>t) return;
    	if(l==r)
    	{
    		for(int i=h; i<=t; ++i) Ans[q[i].id]=l;
    		return;
    	}
    	bool fg=0;
    	for(int i=h; i<=t; ++i) if(q[i].id) {fg=1; break;}
    	if(!fg) return;
    	int m=l+r>>1,t1=0,t2=0;
    	for(int i=h; i<=t; ++i)
    		if(q[i].id)
    		{
    			int tmp=T.Query(q[i].r)-T.Query(q[i].l-1);
    			if(tmp>=q[i].k) q1[t1++]=q[i];
    			else q[i].k-=tmp, q2[t2++]=q[i];
    		}
    		else if(q[i].r<=m) T.Add(q[i].l,q[i].k), q1[t1++]=q[i];
    		else q2[t2++]=q[i];
    	for(int i=h; i<=t; ++i) if(!q[i].id&&q[i].r<=m) T.Clear(q[i].l);
    	for(int i=h,p=0; p<t1; q[i++]=q1[p++]);
    	for(int i=h+t1,p=0; p<t2; q[i++]=q2[p++]);
    	Solve(l,m,h,h+t1-1), Solve(m+1,r,h+t1,t);
    }
    
    int main()
    {
    	int n=read(),Q=read(),tot=0,now=n,mn=1e9,mx=0;
    	for(int i=1; i<=n; ++i) q[i]=(Operation){i,A[i]=read(),1,0},mx=std::max(mx,A[i]),mn=std::min(mn,A[i]);
    	for(int i=1,p; i<=Q; ++i)
    		if(GetOpt()=='Q') q[++now]=(Operation){read(),read(),read(),++tot};
    		else p=read(),q[++now]=(Operation){p,A[p],-1,0},q[++now]=(Operation){p,A[p]=read(),1,0},mx=std::max(mx,A[p]),mn=std::min(mn,A[p]);//修改原数列!
    	T.n=n, Solve(mn,mx,1,now);
    	for(int i=1; i<=tot; ++i) printf("%d
    ",Ans[i]);
    
    	return 0;
    }
    

    数据结构

    线段树、树状数组、Trie树、树剖、二维线段树、主席树略
    树分块...我还不会卡不掉的树分块。。。

    线段树合并✔

    Merge的时候不要写Update(x)就好了...

    分块✔

    查询区间(k)的倍数时,对于整块加(val),可以变成求这块模(k=k-val)的数的个数,这样只需要维护一个模数标记(初始为(0)),这样就将整块加转化成了标记的(O(1))修改。
    这个思路挺好的,应该能拓展。

    K-D Tree

    LCT

    http://www.cnblogs.com/SovietPower/category/1182810.html

    //520ms	2984KB
    //https://www.cnblogs.com/SovietPower/p/8615938.html
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    #define MAXIN 300000
    //#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    typedef long long LL;
    const int N=3e5+5;
    
    char IN[MAXIN],*SS=IN,*TT=IN;
    struct LCT
    {
    	#define ls son[x][0]
    	#define rs son[x][1]
    	int fa[N],son[N][2],sum[N],val[N],sk[N];
    	bool rev[N];
    	inline void Update(int x)
    	{
    		sum[x]=sum[ls]^sum[rs]^val[x];
    	}
    	inline bool n_root(int x)
    	{
    		return son[fa[x]][0]==x||son[fa[x]][1]==x;
    	}
    	inline void Rev(int x)
    	{
    		std::swap(ls,rs), rev[x]^=1;
    	}
    	inline void PushDown(int x)
    	{
    		if(rev[x]) Rev(ls), Rev(rs), rev[x]=0;
    	}
    	void Rotate(int x)
    	{
    		int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
    		if(n_root(a)) son[b][son[b][1]==a]=x;
    		if(son[x][r]) fa[son[x][r]]=a;
    		fa[x]=b, fa[a]=x, son[a][l]=son[x][r], son[x][r]=a;
    		Update(a);
    	}
    	void Splay(int x)
    	{
    		int t=1,a=x; sk[1]=a;
    		while(n_root(a)) sk[++t]=a=fa[a];
    		while(t) PushDown(sk[t--]);
    		while(n_root(x))
    		{
    			if(n_root(a=fa[x])) Rotate(son[a][0]==x^son[fa[a]][0]==a?x:a);
    			Rotate(x);
    		}
    		Update(x);
    	}
    	void Access(int x)
    	{
    		for(int pre=0; x; x=fa[pre=x])
    			Splay(x), rs=pre, Update(x);
    	}
    	void MakeRoot(int x)
    	{
    		Access(x), Splay(x), Rev(x);
    	}
    	void Split(int x,int y)
    	{
    		MakeRoot(x), Access(y), Splay(y);
    	}
    	int FindRoot(int x)
    	{
    		Access(x), Splay(x);
    		while(ls) x=ls;
    		return x;
    	}
    	void Link(int x,int y)
    	{
    		MakeRoot(x);
    		if(FindRoot(y)!=x) fa[x]=y;
    	}
    	void Cut(int x,int y)
    	{
    		MakeRoot(x);
    		if(FindRoot(y)==x&&fa[x]==y&&!rs) fa[x]=son[y][0]=0, Update(y);
    	}
    }T;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now;
    }
    
    int main()
    {
    	int n=read(),q=read();
    	for(int i=1; i<=n; ++i) T.val[i]=read();
    	for(int x,y; q--; )
    		switch(read())
    		{
    			case 0: x=read(),y=read(),T.Split(x,y),printf("%d
    ",T.sum[y]); break;
    			case 1: x=read(),y=read(),T.Link(x,y); break;
    			case 2: x=read(),y=read(),T.Cut(x,y); break;
    			case 3: T.Splay(x=read()),T.val[x]=read(); break;
    		}
    
    	return 0;
    }
    

    可持久化Trie✔

    https://i.cnblogs.com/posts?categoryid=1161664

    Splay

    http://www.cnblogs.com/SovietPower/p/8435011.html

    fhq Treap

    http://www.cnblogs.com/SovietPower/p/8431909.html

    虚树

    可并堆 左偏树*

    http://www.cnblogs.com/SovietPower/p/8435041.html


    数学,数论

    CRT

    扩展CRT

    Lucas

    扩展Lucas

    杜教筛✔

    Min25筛

    莫比乌斯反演✔

    FFT,NTT✔

    #include <cmath>
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=(1<<21)+5;
    const double PI=acos(-1);
    
    int rev[N];
    struct Complex
    {
    	double x,y;
    	Complex(double x=0,double y=0):x(x),y(y) {}
    	inline Complex operator +(const Complex &a)const {return Complex(x+a.x, y+a.y);}
    	inline Complex operator -(const Complex &a)const {return Complex(x-a.x, y-a.y);}
    	inline Complex operator *(const Complex &a)const {return Complex(x*a.x-y*a.y, x*a.y+y*a.x);}
    }f[N],g[N],W[N];
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now;
    }
    void FFT(Complex *a,int lim,int opt)
    {
    	static Complex w[N];
    	for(int i=0; i<lim; ++i) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
    	for(int i=2; i<=lim; i<<=1)
    	{
    		int mid=i>>1;
    		Complex Wn(cos(PI/mid),opt*sin(PI/mid));
    		for(int j=0; j<lim; j+=i)
    		{
    			Complex w(1,0),t;
    			for(int k=j; k<j+mid; ++k,w=w*Wn)
    				a[k+mid]=a[k]-(t=w*a[k+mid]), a[k]=a[k]+t;
    		}
    //		if(~opt) for(int k=0,t=lim/i; k<mid; ++k) w[k]=W[k*t];
    //		else for(int k=0,t=lim/i; k<mid; ++k) w[k]=Complex(W[k*t].x,-W[k*t].y);
    //		for(int j=0; j<lim; j+=i)
    //		{
    //			Complex t;
    //			for(int k=j; k<j+mid; ++k)
    //				a[k+mid]=a[k]-(t=w[k-j]*a[k+mid]), a[k]=a[k]+t;
    //		}
    	}
    	if(opt==-1) for(int i=0; i<lim; ++i) a[i].x/=lim;
    }
    
    int main()
    {
    	int n=read()+1,m=read()+1;
    	for(int i=0; i<n; ++i) f[i].x=read();
    	for(int i=0; i<m; ++i) g[i].x=read();
    	int lim=1,bit=-1;
    	while(lim<=n+m) lim<<=1,++bit;
    	for(int i=1; i<lim; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<bit);
    //	for(int i=0,t=lim>>1; i<lim; ++i) W[i]=Complex(cos(i*PI/t),sin(i*PI/t));
    
    	FFT(f,lim,1), FFT(g,lim,1);
    	for(int i=0; i<lim; ++i) f[i]=f[i]*g[i];
    	FFT(f,lim,-1);
    	for(int i=0,l=n+m-2; i<=l; ++i) printf("%d ",int(f[i].x+0.5));
    
    	return 0;
    }
    
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define mod 998244353
    #define G 3
    #define invG 332748118
    #define Mod(x) x>=mod&&(x-=mod)
    #define gc() getchar()
    typedef long long LL;
    const int N=(1<<21)+5;
    
    int f[N],g[N],rev[N];
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now;
    }
    inline int FP(int x,int k)
    {
    	int t=1;
    	for(; k; k>>=1,x=1ll*x*x%mod) k&1&&(t=1ll*t*x%mod);
    	return t;
    }
    void NTT(int *a,int lim,int opt)
    {
    	for(int i=0; i<lim; ++i) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
    	for(int i=2; i<=lim; i<<=1)
    	{
    		int mid=i>>1; LL Wn=FP(~opt?G:invG,(mod-1)/i);
    		for(int j=0; j<lim; j+=i)
    			for(int k=j,t,w=1; k<j+mid; ++k,w=w*Wn%mod)
    				a[k+mid]=a[k]+mod-(t=1ll*w*a[k+mid]%mod), Mod(a[k+mid]), a[k]+=t, Mod(a[k]);
    	}
    	if(opt==-1) for(int i=0,inv=FP(lim,mod-2); i<lim; ++i) a[i]=1ll*a[i]*inv%mod;
    }
    
    int main()
    {
    	int n=read()+1,m=read()+1;
    	for(int i=0; i<n; ++i) f[i]=read();
    	for(int i=0; i<m; ++i) g[i]=read();
    	int lim=1,bit=-1;
    	while(lim<=n+m) lim<<=1,++bit;
    	for(int i=1; i<lim; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<bit);
    
    	NTT(f,lim,1), NTT(g,lim,1);
    	for(int i=0; i<lim; ++i) f[i]=1ll*f[i]*g[i]%mod;
    	NTT(f,lim,-1);
    	for(int i=0,l=n+m-2; i<=l; ++i) printf("%d ",f[i]);
    
    	return 0;
    }
    

    FWT✔

    BSGS

    Miller Rabin*

    Pollard Rho*

    Catalan数 Stirling数

    高斯消元

    拉格朗日插值✔

    单纯形*

    线性基


    博弈论


    图论

    最短路、生成树、次小生成树略。

    Prufer序列

    Tarjan

    差分约束

    二分图匹配

    欧拉路、哈密顿路

    圆方树

    支配树*

    2-SAT*

    Matrix Tree*

    http://www.cnblogs.com/SovietPower/p/8463968.html


    网络流

    Dinic、ISAP、费用流略。

    无源汇上下界网络流✔

    有源汇上下界网络流✔

    有源汇上下界最小流✔


    字符串

    KMP✔

    https://www.luogu.org/recordnew/show/15171303

    Manacher✔

    http://www.cnblogs.com/SovietPower/p/8677979.html

    回文树✔

    //110ms	34876KB
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=3e5+5;
    
    struct PAM
    {
    	int tot,las,fail[N],len[N],val[N],son[N][26];
    	char s[N];
    	PAM() {tot=1, las=0, fail[0]=1, len[1]=-1, s[0]='$';}
    	inline int Find(int x,int n)
    	{
    		while(s[n-len[x]-1]!=s[n]) x=fail[x];
    		return x;
    	}
    	void Insert(int c,int n)
    	{
    		int p=Find(las,n);
    		if(!son[p][c])
    		{
    			int np=++tot; fail[np]=son[Find(fail[p],n)][c];
    			son[p][c]=np, len[np]=len[p]+2;
    		}
    		++val[las=son[p][c]];
    	}
    	void Solve()
    	{
    		scanf("%s",s+1); int n=strlen(s+1);
    		for(int i=1; i<=n; ++i) Insert(s[i]-'a',i);
    		LL ans=0;
    		for(int x=tot; x>1; --x)
    			ans=std::max(ans,1ll*val[x]*len[x]), val[fail[x]]+=val[x];
    		printf("%lld
    ",ans);
    	}
    }pam;
    
    int main()
    {
    	pam.Solve();
    	return 0;
    }
    

    后缀数组✔

    //297ms	15228kb
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=1e6+5;
    
    struct Suffix_Array
    {
    	int rk[N],sa[N],sa2[N],tm[N],ht[N];
    	char s[N];
    	void Build(char *s,int n,int m)
    	{
    		int *x=rk,*y=sa2;
    		for(int i=0; i<=m; ++i) tm[i]=0;
    		for(int i=1; i<=n; ++i) ++tm[x[i]=s[i]-'a'+1];
    		for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
    		for(int i=n; i; --i) sa[tm[x[i]]--]=i;
    		for(int k=1,p=0; k<n; k<<=1,m=p,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=1; i<=m; ++i) tm[i]=0;
    			for(int i=1; i<=n; ++i) ++tm[x[i]];
    			for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
    			for(int i=n; i; --i) sa[tm[x[y[i]]]--]=y[i];
    
    			std::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;
    		}
    		for(int i=1; i<=n; ++i) rk[sa[i]]=i;
    		ht[1]=0;
    		for(int i=1,k=0; i<=n; ++i)
    		{
    			if(rk[i]==1) continue;
    			if(k) --k;
    			int p=sa[rk[i]-1];
    			while(i+k<=n && p+k<=n && s[i+k]==s[p+k]) ++k;
    			ht[rk[i]]=k;
    		}
    	}
    	void Solve()
    	{
    		scanf("%s",s+1); int n=strlen(s+1);
    		Build(s,n,27);
    		for(int i=1; i<=n; ++i) printf("%d ",sa[i]); puts("");
    		for(int i=2; i<=n; ++i) printf("%d ",ht[i]); puts("");
    	}
    }sa;
    
    int main()
    {
    	sa.Solve();
    	return 0;
    }
    

    AC自动机

    http://www.cnblogs.com/SovietPower/p/8530327.html

    后缀自动机


    其它

    dsu on tree

    长链剖分

    高维前缀和✔

    带权二分

    模拟退火

    一般莫队✔

    常搭配分块使用(莫队本身(O(nsqrt n))次修改,(O(n))次查询)。
    优化什么的(分奇偶),不管惹。

    带修改莫队

    回滚莫队✔

    还是将所有询问按((左端点所在块, 右端点))排序。对于左右端点在同一块里的询问,暴力查询。
    否则,把左端点在同一块(i)里的询问一起处理。这时右端点一定是递增的。
    (l)为第(i+1)块(下一块)的左端点,(r)为第(i)块(该块)的右端点。将(r)移动到当前询问的右端点处并更新答案,记录此时答案(tmp=Now)
    (l)移动到当前询问的左端点处并更新答案,得到当前询问的答案(Now)
    (l)移回到下一块左端点位置,并消除影响(减掉加的次数之类的),并令(Now=tmp)

  • 相关阅读:
    Linux程序调试GDB——数据查看
    linux C++ 共享库导出类
    MyBatis 通用Mapper接口 Example的实例
    mybatis3 @SelectProvider
    Maven命令行使用 mvn clean package
    Springboot IDEA eclipse 打包
    Intellij IDEA Debug
    SpringCloud之Eureka 服务注册和服务发现基础篇2
    SpringCloud组件和概念介绍1
    IntelliJ IDEA SVN
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10655291.html
Copyright © 2020-2023  润新知