我的模板库

马上就要考APIO和CTSC了,总结一下考试中可能会用的模板和注意点。

以后还会持续更新哦


计算几何


1.凸包

//bzoj1670 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 5005
using namespace std;
int n,top;
double ans;
struct P{int x,y;}p[maxn],s[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline P operator-(const P &a,const P &b)
{
	return (P){a.x-b.x,a.y-b.y};
}
inline ll operator*(const P &a,const P &b)
{
	return a.x*b.y-a.y*b.x;
}
inline ll dis(P a,P b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
inline bool operator<(const P &a,const P &b)
{
	ll t=(a-p[1])*(b-p[1]);
	if (t==0) return dis(p[1],a)<dis(p[1],b);
	else return t<0;
}
inline void solve()
{
	int t=1;
	F(i,2,n) if (p[i].y<p[t].y||(p[i].y==p[t].y&&p[i].x<p[t].x)) t=i;
	swap(p[1],p[t]);
	sort(p+2,p+n+1);
	s[++top]=p[1];s[++top]=p[2];
	F(i,3,n)
	{
		while (top>=2&&(s[top]-s[top-1])*(p[i]-s[top-1])>=0) top--;
		s[++top]=p[i];
	}
	s[top+1]=p[1];
	F(i,1,top) ans+=sqrt(dis(s[i],s[i+1]));
}
int main()
{
	n=read();
	F(i,1,n) p[i].x=read(),p[i].y=read();
	solve();
	printf("%.2lf\n",ans);
	return 0;
}

2.旋转卡壳

//bzoj1069 凸包+旋转卡壳 
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 2005
#define eps 1e-8
using namespace std;
int n,top;
double ans;
struct data{double x,y;}p[maxn],s[maxn];
inline double dcmp(double a)
{
	if (fabs(a)<=eps) return 0;
	else return a>0?1:-1;
}
inline double dis(data a,data b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
inline data operator -(data a,data b)
{
	return (data){a.x-b.x,a.y-b.y};
}
inline double operator *(data a,data b)
{
	return a.x*b.y-a.y*b.x;
}
inline bool operator <(data a,data b)
{
	int t=dcmp((p[1]-a)*(p[1]-b));
	if (t==0) return dis(p[1],a)<dis(p[1],b);
	else return t>0;
}
inline void solve()
{
	int t=1;
	F(i,2,n) if (p[i].y<p[t].y||(p[i].y==p[t].y&&p[i].x<p[t].x)) t=i;
	swap(p[t],p[1]);
	sort(p+2,p+n+1);
	s[++top]=p[1];s[++top]=p[2];
	F(i,3,n)
	{
		while (top>1&&dcmp((p[i]-s[top-1])*(s[top]-s[top-1]))>=0) top--;
		s[++top]=p[i];
	}
}
inline void getans()
{
	int a,b;
	s[top+1]=s[1];
	F(x,1,top-2)
	{
		a=x%top+1;b=(x+2)%top+1;
		F(y,x+2,top)
		{
			while (a%top+1!=y&&dcmp((s[a+1]-s[x])*(s[y]-s[x])-(s[a]-s[x])*(s[y]-s[x]))>0) a=a%top+1;
			while (b%top+1!=x&&dcmp((s[y]-s[x])*(s[b+1]-s[x])-(s[y]-s[x])*(s[b]-s[x]))>0) b=b%top+1;
			ans=max(ans,(s[a]-s[x])*(s[y]-s[x])+(s[y]-s[x])*(s[b]-s[x]));
		}
	}
}
int main()
{
	scanf("%d",&n);
	F(i,1,n) scanf("%lf%lf",&p[i].x,&p[i].y);
	solve();
	getans();
	printf("%.3lf\n",ans/2.0);
	return 0;
}

3.半平面交

//bzoj2618 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 1000
#define eps 1e-8
using namespace std;
int n,m,cnt,tot;
double ans;
struct P{double x,y;}p[maxn],a[maxn];
struct L{P a,b;double angle;}l[maxn],q[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline P operator -(P a,P b){return (P){a.x-b.x,a.y-b.y};}
inline double operator *(P a,P b){return a.x*b.y-a.y*b.x;}
inline bool operator <(L l1,L l2)
{
	if (fabs(l1.angle-l2.angle)<=eps) return (l1.a-l2.a)*(l1.b-l2.a)>0;
	else return l1.angle<l2.angle;
}
inline P inter(L l1,L l2)
{
	double k1=(l2.b-l1.a)*(l1.b-l1.a),k2=(l1.b-l1.a)*(l2.a-l1.a),t=k1/(k1+k2);
	return (P){l2.b.x+(l2.a.x-l2.b.x)*t,l2.b.y+(l2.a.y-l2.b.y)*t};
}
inline bool judge(L a,L b,L t)
{
	P p=inter(a,b);
	return (p-t.a)*(t.b-t.a)>eps;
}
inline void hpi()
{
	sort(l+1,l+cnt+1);
	int head=1,tail=0;tot=1;
	F(i,2,cnt)
	{
		if (fabs(l[i].angle-l[i-1].angle)>eps) tot++;
		l[tot]=l[i];
	}
	cnt=tot;
	q[++tail]=l[1];q[++tail]=l[2];
	F(i,3,cnt)
	{
		while (head<tail&&judge(q[tail],q[tail-1],l[i])) tail--;
		while (head<tail&&judge(q[head],q[head+1],l[i])) head++;
		q[++tail]=l[i];
	}
	while (head<tail&&judge(q[tail],q[tail-1],q[head])) tail--;
	tot=0;
	F(i,head,tail-1) a[++tot]=inter(q[i],q[i+1]);
	a[++tot]=inter(q[head],q[tail]);
}
int main()
{
	n=read();
	while (n--)
	{
		m=read();
		F(i,1,m) p[i].x=read(),p[i].y=read();
		F(i,1,m-1) l[++cnt]=(L){p[i],p[i+1]};
		l[++cnt]=(L){p[m],p[1]};
	}
	F(i,1,cnt) l[i].angle=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
	hpi();
	a[tot+1]=a[1];
	F(i,1,tot) ans+=a[i]*a[i+1];
	printf("%.3lf\n",ans/2);
	return 0;
}

4.最小圆覆盖

//bzoj1336 随机增量法求最小圆覆盖 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 100005
#define eps 1e-8
using namespace std;
int n;
double r;
struct P
{
	double x,y;
	friend P operator +(P a,P b){return (P){a.x+b.x,a.y+b.y};}
	friend P operator -(P a,P b){return (P){a.x-b.x,a.y-b.y};}
	friend P operator /(P a,double b){return (P){a.x/b,a.y/b};}
}p[maxn],t;
inline double dis(P a,P b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline P rev(P a)
{
	return (P){a.y,-a.x};
}
inline P centre(P a,P b,P c)
{
	if (fabs((a.x-b.x)*(a.y-c.y)-(a.x-c.x)*(a.y-b.y))<=eps)
	{
		if (a.x<b.x) swap(a,b);
		if (a.x<c.x) swap(a,c);
		if (b.x<c.x) swap(b,c);
		return (a+c)/2;
	}
	P x1=(a+b)/2,x2=x1+rev(a-b),y1=(a+c)/2,y2=y1+rev(a-c);
	if (fabs(y1.x-y2.x)<eps) swap(x1,y1),swap(x2,y2);
	double k2=(y1.y-y2.y)/(y1.x-y2.x),b2=y2.y-y2.x*k2;
	if (fabs(x1.x-x2.x)<eps) return (P){x1.x,k2*x1.x+b2};
	double k1=(x1.y-x2.y)/(x1.x-x2.x),b1=x2.y-x2.x*k1;
	double x=(b2-b1)/(k1-k2);
	return (P){x,k1*x+b1};
}
int main()
{
	scanf("%d",&n);
	F(i,1,n) scanf("%lf%lf",&p[i].x,&p[i].y);
	random_shuffle(p+1,p+n+1);
	t=p[1];r=0.0;
	F(i,2,n) if (dis(t,p[i])>r+eps)
	{
		t=(p[1]+p[i])/2;r=dis(p[i],t);
		F(j,2,i-1) if (dis(t,p[j])>r+eps)
		{
			t=(p[i]+p[j])/2;r=dis(p[i],t);
			F(k,1,j-1) if (dis(t,p[k])>r+eps)
			{
				t=centre(p[i],p[j],p[k]);
				r=dis(p[i],t);
			}
		}
	}
	printf("%.10lf\n%.10lf %.10lf\n",r,t.x,t.y);
	return 0;
}


数据结构


1.线段树

//bzoj1798 加法乘法双标记线段树 
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define MAXN 100005
using namespace std;
struct tree_type
{
	int l,r;
	LL tmp_1,tmp_2,sum;
}t[MAXN*4];
int n,m,p,opt,L,R,c,a[MAXN];
void build(int num,int l,int r)
{
	t[num].l=l;
	t[num].r=r;
	t[num].tmp_1=0;
	t[num].tmp_2=1;
	if (l==r)
	{
		t[num].sum=a[l]%p;
		return;
	}
	int mid=(l+r)/2;
	build(num*2,l,mid);
	build(num*2+1,mid+1,r);
	t[num].sum=(t[num*2].sum+t[num*2+1].sum)%p;
	return;
}
void push_down(int num)
{
	if (t[num].tmp_2==1&&t[num].tmp_1==0) return;
	t[num*2].tmp_1=(t[num*2].tmp_1*t[num].tmp_2+t[num].tmp_1)%p;
	t[num*2+1].tmp_1=(t[num*2+1].tmp_1*t[num].tmp_2+t[num].tmp_1)%p;
	t[num*2].tmp_2=(t[num*2].tmp_2*t[num].tmp_2)%p;
	t[num*2+1].tmp_2=(t[num*2+1].tmp_2*t[num].tmp_2)%p;
	t[num*2].sum=(t[num*2].sum*t[num].tmp_2+(t[num*2].r-t[num*2].l+1)*t[num].tmp_1)%p;
	t[num*2+1].sum=(t[num*2+1].sum*t[num].tmp_2+(t[num*2+1].r-t[num*2+1].l+1)*t[num].tmp_1)%p;
	t[num].tmp_1=0;
	t[num].tmp_2=1;
	return;
}
void add(int num,int l,int r,int x)
{
	if (t[num].l>r||t[num].r<l) return;
	if (t[num].l>=l&&t[num].r<=r)
	{
		t[num].tmp_1=(t[num].tmp_1+x)%p;
		t[num].sum=(t[num].sum+(t[num].r-t[num].l+1)*x)%p;
		return;
	}
	push_down(num);
	add(num*2,l,r,x);
	add(num*2+1,l,r,x);
	t[num].sum=(t[num*2].sum+t[num*2+1].sum)%p;
	return;
}
void multiply(int num,int l,int r,int x)
{
	if (t[num].l>r||t[num].r<l) return;
	if (t[num].l>=l&&t[num].r<=r)
	{
		t[num].tmp_1=(t[num].tmp_1*x)%p;
		t[num].tmp_2=(t[num].tmp_2*x)%p;
		t[num].sum=(t[num].sum*x)%p;
		return;
	}
	push_down(num);
	multiply(num*2,l,r,x);
	multiply(num*2+1,l,r,x);
	t[num].sum=(t[num*2].sum+t[num*2+1].sum)%p;
	return;
}
LL ask(int num,int l,int r)
{
	if (t[num].l>r||t[num].r<l) return 0;
	if (t[num].l>=l&&t[num].r<=r) return t[num].sum%p;
	push_down(num);
	return (ask(num*2,l,r)+ask(num*2+1,l,r))%p;
}
int main()
{
//	freopen("input.in","r",stdin);
	scanf("%d%d",&n,&p);
	F(i,1,n) scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&m);
	F(i,1,m)
	{
		scanf("%d",&opt);
		if (opt==1)
		{
			scanf("%d%d%d",&L,&R,&c);
			multiply(1,L,R,c);
		}
		if (opt==2)
		{
			scanf("%d%d%d",&L,&R,&c);
			add(1,L,R,c);
		}
		if (opt==3)
		{
			scanf("%d%d",&L,&R);
			printf("%lld\n",ask(1,L,R)%p);
		}
	}
	return 0;
}

2.树状数组

//poj2299
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<map>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define MAXN 500005
#define pa pair<int,int>
using namespace std;
int n,b[MAXN],f[MAXN];
LL ans;
struct data
{
	int val,pos;
}a[MAXN];
int read()
{
	int ret=0,flag=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
	return ret*flag;
}
void add(int k)
{
	for(int i=k;i<=n;i+=i&(-i)) f[i]++;
}
LL getsum(int k)
{
	LL ret=0;
	for(int i=k;i>0;i-=i&(-i)) ret+=f[i];
	return ret;
}
bool cmp(data x,data y)
{
	return x.val<y.val;
}
int main()
{
	n=read();
	while (n)
	{
		memset(f,0,sizeof(f));
		ans=0;
		F(i,1,n) a[i].val=read(),a[i].pos=i;
		sort(a+1,a+n+1,cmp);
		F(i,1,n)
		{
			if (i>1&&a[i].val==a[i-1].val) b[a[i].pos]=b[a[i-1].pos];
			else b[a[i].pos]=i;
		}
		D(i,n,1)
		{
			if (b[i]>1) ans+=getsum(b[i]-1);
			add(b[i]);
		}
		printf("%lld\n",ans);
		n=read();
	}
}

3.Splay

//bzoj1269 Splay维护区间操作 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 2100000
#define INF 1000000000
#define key c[c[rt][1]][0]
using namespace std;
int pos=1,rt=0,tot=0,n,x,c[MAXN][2],s[MAXN],fa[MAXN];
char v[MAXN],op[10],ch[MAXN];
bool rev[MAXN];
inline void pushup(int k)
{
	if (!k) return;
	s[k]=s[c[k][0]]+s[c[k][1]]+1;
}
inline void update(int k)
{
	if (!k) return;
	rev[k]^=1;
	swap(c[k][0],c[k][1]);
}
inline void pushdown(int k)
{
	if (!k) return;
	if (rev[k])
	{
		update(c[k][0]);update(c[k][1]);
		rev[k]=0;
	}
}
inline void rotate(int x,int &k)
{
	int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1;
	if (y==k) k=x;
	else c[z][c[z][1]==y]=x;
	fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
	c[y][l]=c[x][r];c[x][r]=y;
	pushup(y);pushup(x);
}
inline void splay(int x,int &k)
{
	while (x!=k)
	{
		int y=fa[x],z=fa[y];
		if (y!=k)
		{
			if ((c[y][0]==x)^(c[z][0]==y)) rotate(x,k);
			else rotate(y,k);
		}
		rotate(x,k);
	}
}
inline int find(int k,int rank)
{
	pushdown(k);
	int l=c[k][0],r=c[k][1];
	if (s[l]+1==rank) return k;
	else if (s[l]>=rank) return find(l,rank);
	else return find(r,rank-s[l]-1);
}
inline void split(int l,int r)
{
	int x=find(rt,l-1),y=find(rt,r+1);
	splay(x,rt);splay(y,c[rt][1]);
}
inline void newnode(int &k,char ch,int last)
{
	k=++tot;
	fa[k]=last;
	v[k]=ch;
	c[k][0]=c[k][1]=rev[k]=0;
	s[k]=1;
}
inline void ins(int &k,int l,int r,int last)
{
	int mid=(l+r)>>1;
	newnode(k,ch[mid],last);
	if (l<mid) ins(c[k][0],l,mid-1,k);
	if (mid<r) ins(c[k][1],mid+1,r,k);
	pushup(k);
}
inline void solveins()
{
	scanf("%d%*c",&x);
	gets(ch);
	split(pos+1,pos);
	ins(key,0,x-1,c[rt][1]);
	pushup(c[rt][1]);pushup(rt);
}
inline void solvedel()
{
	scanf("%d%*c",&x);
	split(pos+1,pos+x);
	fa[key]=0;key=0;
	pushup(c[rt][1]);pushup(rt);
}
inline void solverev()
{
	scanf("%d%*c",&x);
	split(pos+1,pos+x);
	update(key);
}
int main()
{
	newnode(rt,'*',0);newnode(c[rt][1],'*',rt);pushup(rt);
	scanf("%d%*c",&n);
	F(i,1,n)
	{
		scanf("%s%*c",op);
		if (op[0]=='M') {scanf("%d%*c",&x);pos=x+1;}
		else if (op[0]=='I') solveins();
		else if (op[0]=='D') solvedel();
		else if (op[0]=='R') solverev();
		else if (op[0]=='G') printf("%c\n",v[find(rt,pos+1)]);
		else if (op[0]=='P') pos--;
		else pos++;
	}
}

4.Treap

//bzoj1208
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 80005
#define INF 1000000000000
#define mod 1000000
using namespace std;
int rt=0,tot=0,l[MAXN],r[MAXN];
LL n,x,y,flag=0,sum=0,sz=0,v[MAXN],rnd[MAXN];
inline LL read()
{
	LL x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void rturn(int &k){int tmp=l[k];l[k]=r[tmp];r[tmp]=k;k=tmp;}
inline void lturn(int &k){int tmp=r[k];r[k]=l[tmp];l[tmp]=k;k=tmp;}
inline void ins(int &k,LL x)
{
	if (!k){k=++tot;l[k]=r[k]=0;v[k]=x;rnd[k]=rand();return;}
	if (x<v[k]){ins(l[k],x);if (rnd[l[k]]<rnd[k]) rturn(k);}
	else {ins(r[k],x);if (rnd[r[k]]<rnd[k]) lturn(k);}
}
inline void del(int &k,LL x)
{
	if (v[k]==x)
	{
		if (!l[k]||!r[k]) k=l[k]+r[k];
		else
		{
			if (rnd[l[k]]<rnd[r[k]]){rturn(k);del(k,x);}
			else {lturn(k);del(k,x);}
		}
		return;
	}
	else if (v[k]>x) del(l[k],x);
	else del(r[k],x);
}
inline LL pre(int k,LL x)
{
	if (!k) return -INF;
	if (x==v[k]) return v[k];
	if (x<v[k]) return pre(l[k],x);
	else
	{
		LL tmp=pre(r[k],x);
		return tmp==-INF?v[k]:tmp;
	}
}
inline LL suc(int k,LL x)
{
	if (!k) return INF;
	if (x==v[k]) return v[k];
	if (x>v[k]) return suc(r[k],x);
	else
	{
		LL tmp=suc(l[k],x);
		return tmp==INF?v[k]:tmp;
	}
}
inline void solve(LL x)
{
	LL ans=pre(rt,x),tmp=suc(rt,x);
	if (abs(x-tmp)<abs(x-ans)) ans=tmp;
	sum=(sum+abs(x-ans))%mod;
	del(rt,ans);
}
int main()
{
	n=read();
	while(n--)
	{
		x=read();y=read();
		if (!sz){ins(rt,y);flag=x;sz++;}
		else if (flag==x){ins(rt,y);sz++;}
		else {solve(y);sz--;}
	}
	printf("%lld\n",sum);
}

5.Trie

//poj2001
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define maxn 20005
#define inf 1000000000
using namespace std;
struct trie_type
{
	int cnt,next[30];
}t[maxn];
int tot=0,n=0;
char s[1005][25];
inline void insert(char *ch)
{
	int p=0,l=strlen(ch);
	F(i,0,l-1)
	{
		int tmp=ch[i]-'a';
		if (!t[p].next[tmp]) t[p].next[tmp]=++tot;
		p=t[p].next[tmp];
		t[p].cnt++;
	}
}
inline void find(char *ch)
{
	int p=0,l=strlen(ch);
	printf("%s ",ch);
	F(i,0,l-1)
	{
		printf("%c",ch[i]);
		int tmp=ch[i]-'a';
		p=t[p].next[tmp];
		if (t[p].cnt==1) break;
	}
	printf("\n");
}
int main()
{
	while (~scanf("%s",s[++n])) insert(s[n]);
	F(i,1,n-1) find(s[i]);
}

6.划分树

//poj2104 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 100005
using namespace std;
int n,m,a[MAXN],val[20][MAXN],num[20][MAXN];
inline int read()
{
	int ret=0,flag=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
	return ret*flag;
}
inline void build(int l,int r,int x)
{
	if (l==r) return;
	int mid=(l+r)>>1,lsame=mid-l+1,same=0,ln=l,rn=mid+1;
	F(i,l,r) if (val[x][i]<a[mid]) lsame--;
	F(i,l,r)
	{
		if (i==l) num[x][i]=0;else num[x][i]=num[x][i-1];
		if (val[x][i]<a[mid]) num[x][i]++,val[x+1][ln++]=val[x][i];
		else if (val[x][i]>a[mid]) val[x+1][rn++]=val[x][i];
		else
		{
			if (lsame>=++same) num[x][i]++,val[x+1][ln++]=val[x][i];
			else val[x+1][rn++]=val[x][i];
		}
	}
	build(l,mid,x+1);
	build(mid+1,r,x+1);
}
inline int query(int st,int ed,int k,int l,int r,int x)
{
	if (l==r) return val[x][l];
	int lx,ly,rx,ry,mid=(l+r)>>1;
	if (st==l) lx=0,ly=num[x][ed];
	else lx=num[x][st-1],ly=num[x][ed]-lx;
	if (ly>=k)
	{
		st=l+lx;ed=st+ly-1;
		return query(st,ed,k,l,mid,x+1);
	}
	else
	{
		rx=st-l-lx;ry=ed-st+1-ly;
		st=mid+1+rx;ed=st+ry-1;
		return query(st,ed,k-ly,mid+1,r,x+1);
	}
}
int main()
{
	n=read();m=read();
	F(i,1,n) val[0][i]=a[i]=read();
	sort(a+1,a+n+1);
	build(1,n,0);
	F(i,1,m)
	{
		int x=read(),y=read(),k=read();
		printf("%d\n",query(x,y,k,1,n,0));
	}
}

7.K-D Tree

//bzoj2648 K-D Tree 最近邻搜索 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 500005
#define inf 1000000000
using namespace std;
int n,m,root,D,ans;
struct data
{
	int d[2],mn[2],mx[2],l,r;
}p[maxn],t[maxn*2],tmp;
bool operator<(data a,data b)
{
	return a.d[D]<b.d[D];
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline int dis(data a,data b)
{
	return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);
}
inline void pushup(int k)
{
	int ls=t[k].l,rs=t[k].r;
	F(i,0,1)
	{
		if (ls)
		{
			t[k].mn[i]=min(t[k].mn[i],t[ls].mn[i]);
			t[k].mx[i]=max(t[k].mx[i],t[ls].mx[i]);
		}
		if (rs)
		{
			t[k].mn[i]=min(t[k].mn[i],t[rs].mn[i]);
			t[k].mx[i]=max(t[k].mx[i],t[rs].mx[i]);
		}
	}
}
inline int build(int l,int r,int now)
{
	D=now;
	int mid=(l+r)>>1;
	nth_element(p+l,p+mid,p+r+1);
	t[mid]=p[mid];
	F(i,0,1) t[mid].mn[i]=t[mid].mx[i]=t[mid].d[i];
	if (l<mid) t[mid].l=build(l,mid-1,now^1);
	if (mid<r) t[mid].r=build(mid+1,r,now^1);
	pushup(mid);
	return mid;
}
inline int get(int k,data x)
{
	int tmp=0;
	F(i,0,1) tmp+=max(0,t[k].mn[i]-x.d[i]);
	F(i,0,1) tmp+=max(0,x.d[i]-t[k].mx[i]);
	return tmp;
}
inline void insert(int k,int now)
{
	if (tmp.d[now]>=t[k].d[now])
	{
		if (t[k].r) insert(t[k].r,now^1);
		else
		{
			t[k].r=++n;t[n]=tmp;
			F(i,0,1) t[n].mn[i]=t[n].mx[i]=t[n].d[i];
		}
	}
	else
	{
		if (t[k].l) insert(t[k].l,now^1);
		else
		{
			t[k].l=++n;t[n]=tmp;
			F(i,0,1) t[n].mn[i]=t[n].mx[i]=t[n].d[i];
		}
	}
	pushup(k);
}
inline void query(int k,int now)
{
	int d,dl=inf,dr=inf;
	d=dis(t[k],tmp);
	ans=min(ans,d);
	if (t[k].l) dl=get(t[k].l,tmp);
	if (t[k].r) dr=get(t[k].r,tmp);
	if (dl<dr)
	{
		if (dl<ans) query(t[k].l,now^1);
		if (dr<ans) query(t[k].r,now^1);
	}
	else
	{
		if (dr<ans) query(t[k].r,now^1);
		if (dl<ans) query(t[k].l,now^1);
	}
}
int main()
{
	n=read();m=read();
	F(i,1,n){p[i].l=p[i].r=0;p[i].d[0]=read();p[i].d[1]=read();}
	root=build(1,n,0);
	tmp.l=tmp.r=0;
	while (m--)
	{
		int opt=read();tmp.d[0]=read();tmp.d[1]=read();
		if (opt==1) insert(root,0);
		else
		{
			ans=inf;
			query(root,0);
			printf("%d\n",ans);
		}
	}
	return 0;
}

8.树链剖分

//bzoj2819
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 500005
using namespace std;
struct edge{int next,to;}e[maxn*2];
struct seg{int l,r,w;}t[maxn*4];
int n,m,cnt,tot,x,y;
int a[maxn],d[maxn],f[maxn],p[maxn],fa[maxn],sz[maxn];
int son[maxn],head[maxn],belong[maxn];
char ch;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void add_edge(int x,int y)
{
	e[++cnt]=(edge){head[x],y};head[x]=cnt;
	e[++cnt]=(edge){head[y],x};head[y]=cnt;
}
inline void dfs1(int x)
{
	sz[x]=1;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (sz[y]) continue;
		d[y]=d[x]+1;
		fa[y]=x;
		dfs1(y);
		sz[x]+=sz[y];
		if (sz[y]>sz[son[x]]) son[x]=y;
	}
}
inline void dfs2(int x,int chain)
{
	p[x]=++tot;f[tot]=a[x];belong[x]=chain;
	if (son[x]) dfs2(son[x],chain);
	for(int i=head[x];i;i=e[i].next)
		if (!p[e[i].to]&&e[i].to!=son[x]) dfs2(e[i].to,e[i].to);
}
inline void pushup(int k)
{
	t[k].w=t[k<<1].w^t[k<<1|1].w;
}
inline void build(int k,int l,int r)
{
	t[k].l=l;t[k].r=r;
	if (l==r){t[k].w=f[l];return;}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);build(k<<1|1,mid+1,r);
	pushup(k);
}
inline int query(int k,int x,int y)
{
	if (t[k].l==x&&t[k].r==y) return t[k].w;
	int mid=(t[k].l+t[k].r)>>1;
	if (y<=mid) return query(k<<1,x,y);
	else if (x>mid) return query(k<<1|1,x,y);
	else return query(k<<1,x,mid)^query(k<<1|1,mid+1,y);
}
inline void change(int k,int pos,int x)
{
	if (t[k].l==t[k].r){t[k].w=x;return;}
	int mid=(t[k].l+t[k].r)>>1;
	if (pos<=mid) change(k<<1,pos,x);
	else change(k<<1|1,pos,x);
	pushup(k);
}
int main()
{
	n=read();
	F(i,1,n) a[i]=read();
	F(i,1,n-1) add_edge(read(),read());
	d[1]=1;dfs1(1);dfs2(1,1);
	build(1,1,n);
	m=read();
	F(i,1,m)
	{
		ch=getchar();while (ch<'A'||ch>'Z') ch=getchar();
		x=read();y=read();
		if (ch=='Q')
		{
			int sum=0;
			while (belong[x]!=belong[y])
			{
				if (d[belong[x]]<d[belong[y]]) swap(x,y);
				sum^=query(1,p[belong[x]],p[x]);
				x=fa[belong[x]];
			}
			if (d[x]>d[y]) swap(x,y);
			sum^=query(1,p[x],p[y]);
			if (sum) puts("Yes");
			else puts("No");
		}
		else change(1,p[x],y);
	}
}

9.二维线段树

//bzoj1513 二维线段树标记永久化 
#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1000000000
using namespace std;
ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int D,S,N;
int ql,qr,qd,qu;
struct segx
{
    int v[3005],tag[3005];
    void change(int k,int l,int r,int x,int y,int val)
	{
        v[k]=max(v[k],val);
        if(l==x&&y==r){tag[k]=max(tag[k],val);return;}
        int mid=(l+r)>>1;
        if(x<=mid)change(k<<1,l,mid,x,min(mid,y),val);
        if(y>mid)change(k<<1|1,mid+1,r,max(x,mid+1),y,val);
    }
    int query(int k,int l,int r,int x,int y)
	{
        if(l==x&&y==r)return v[k];
        int mid=(l+r)>>1,ans=tag[k];
        if(x<=mid)ans=max(ans,query(k<<1,l,mid,x,min(mid,y)));
        if(y>mid)ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y));
        return ans;
    }
};
struct segy
{
    segx v[3005],tag[3005];
    void change(int k,int l,int r,int x,int y,int val)
	{
        v[k].change(1,1,S,qd,qu,val);
        if(l==x&&y==r){tag[k].change(1,1,S,qd,qu,val);return;}
        int mid=(l+r)>>1;
        if(x<=mid)change(k<<1,l,mid,x,min(mid,y),val);
        if(y>mid)change(k<<1|1,mid+1,r,max(x,mid+1),y,val);
    }
    int query(int k,int l,int r,int x,int y)
	{
        if(l==x&&r==y)return v[k].query(1,1,S,qd,qu);
        int mid=(l+r)>>1,ans=tag[k].query(1,1,S,qd,qu);
        if(x<=mid)ans=max(ans,query(k<<1,l,mid,x,min(mid,y)));
        if(y>mid)ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y));
        return ans;
    }
}T;
int main()
{
    D=read();S=read();N=read();
    int d,s,w,x,y;
    for(int i=1;i<=N;i++)
    {
        d=read();s=read();w=read();x=read();y=read();
        ql=x+1;qr=x+d;qd=y+1;qu=y+s;
        int ans=T.query(1,1,D,ql,qr);
        T.change(1,1,D,ql,qr,ans+w);
    }
    qd=1;qu=S;
    printf("%d\n",T.query(1,1,D,1,D));
    return 0;
}

10.可持久化线段树

//bzoj3524 
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 500005
#define maxm 10000005
using namespace std;
int n,m,tot;
int rt[maxn],ls[maxm],rs[maxm],sum[maxm];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void update(int l,int r,int x,int &y,int v)
{
	y=++tot;
	sum[y]=sum[x]+1;
	if (l==r) return;
	ls[y]=ls[x];rs[y]=rs[x];
	int mid=(l+r)>>1;
	if (v<=mid) update(l,mid,ls[x],ls[y],v);
	else update(mid+1,r,rs[x],rs[y],v);
}
inline int query(int u,int v)
{
	int l=1,r=n,mid,x=rt[u-1],y=rt[v],tmp=(v-u+1)>>1;
	while (l!=r)
	{
		if (sum[y]-sum[x]<=tmp) return 0;
		mid=(l+r)>>1;
		if (sum[ls[y]]-sum[ls[x]]>tmp){r=mid;x=ls[x];y=ls[y];}
		else if (sum[rs[y]]-sum[rs[x]]>tmp){l=mid+1;x=rs[x];y=rs[y];}
		else return 0;
	}
	return l;
}
int main()
{
	n=read();m=read();
	F(i,1,n)
	{
		int x=read();
		update(1,n,rt[i-1],rt[i],x);
	}
	F(i,1,m)
	{
		int l=read(),r=read();
		printf("%d\n",query(l,r));
	}
	return 0;
}

11.可持久化Trie树

//bzoj3261  
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 600005
#define maxm 20000005
using namespace std;
int n,m,tot=0,sum=0;
int rt[maxn],id[maxm],t[maxm][2];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void insert(int pre,int x,int k)
{
	int now=rt[k]=++tot;id[tot]=k;
	D(i,24,0)
	{
		int j=(x>>i)&1;
		t[now][j^1]=t[pre][j^1];
		t[now][j]=++tot;id[tot]=k;
		now=t[now][j];pre=t[pre][j];
	}
}
inline int query(int l,int r,int x)
{
	int ans=0,tmp=rt[r];
	D(i,24,0)
	{
		if (id[tmp]<l) break;
		int j=((x>>i)&1)^1;
		if (id[t[tmp][j]]>=l) ans|=(1<<i);
		else j^=1;
		tmp=t[tmp][j];
	}
	return ans;
}
int main()
{
	n=read();m=read();
	id[0]=-1;
	insert(0,0,0);
	F(i,1,n)
	{
		sum^=read();
		insert(rt[i-1],sum,i);
	}
	F(i,1,m)
	{
		char ch=getchar();
		while (ch<'A'||ch>'Z') ch=getchar();
		if (ch=='A')
		{
			sum^=read();
			insert(rt[n],sum,n+1);
			n++;
		}
		else
		{
			int l=read(),r=read(),x=read();
			printf("%d\n",query(l-1,r-1,sum^x));
		}
	}
	return 0;
}

12.LCT

//bzoj2049
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 10005
using namespace std;
int n,m;
int fa[maxn],c[maxn][2],st[maxn];
bool rev[maxn];
char ch[10];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline bool isroot(int x)
{
	return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}
inline void pushdown(int k)
{
	int ls=c[k][0],rs=c[k][1];
	if (rev[k])
	{
		rev[k]^=1;rev[ls]^=1;rev[rs]^=1;
		swap(c[k][0],c[k][1]);
	}
}
inline void rotate(int x)
{
	int y=fa[x],z=fa[y],l,r;
	l=(c[y][0]==x)?0:1;
	r=l^1;
	if (!isroot(y))
	{
		if (c[z][0]==y) c[z][0]=x;
		else c[z][1]=x;
	}
	fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
	c[y][l]=c[x][r];c[x][r]=y;
}
inline void splay(int x)
{
	int top=0;st[++top]=x;
	for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
	D(i,top,1) pushdown(st[i]);
	while (!isroot(x))
	{
		int y=fa[x],z=fa[y];
		if (!isroot(y))
		{
			if (c[y][0]==x^c[z][0]==y) rotate(x);
			else rotate(y);
		}
		rotate(x);
	}
}
inline void access(int x)
{
	int t=0;
	while (x)
	{
		splay(x);
		c[x][1]=t;
		t=x;x=fa[x];
	}
}
inline void rever(int x)
{
	access(x);
	splay(x);
	rev[x]^=1;
}
inline void link(int x,int y)
{
	rever(x);
	fa[x]=y;
}
inline void cut(int x,int y)
{
	rever(x);
	access(y);
	splay(y);
	c[y][0]=fa[x]=0;
//	c[x][1]=fa[y]=0;
}
inline int find(int x)
{
	access(x);
	splay(x);
	int t=x;
	while (c[t][0]) t=c[t][0];
	return t;
}
int main()
{
	n=read();m=read();
	F(i,1,m)
	{
		scanf("%s",ch);
		int x=read(),y=read();
		if (ch[0]=='C') link(x,y);
		else if (ch[0]=='D') cut(x,y);
		else puts((find(x)==find(y))?"Yes":"No");
	}
	return 0;
}


数学


1.FFT

//bzoj2179
#include<bits/stdc++.h>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 200000
using namespace std;
const double pi=acos(-1.0);
int n,m,len,rev[maxn],ans[maxn];
char s[maxn];
struct cp
{
	double x,y;
	inline cp operator +(cp a){return (cp){x+a.x,y+a.y};}
	inline cp operator -(cp a){return (cp){x-a.x,y-a.y};}
	inline cp operator *(cp a){return (cp){x*a.x-y*a.y,x*a.y+y*a.x};}
}a[maxn],b[maxn],c[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void fft(cp *x,int n,int flag)
{
	F(i,0,n-1) if (rev[i]>i) swap(x[rev[i]],x[i]);
	for(int m=2;m<=n;m<<=1)
	{
		cp wn=(cp){cos(2.0*pi/m*flag),sin(2.0*pi/m*flag)};
		for(int i=0;i<n;i+=m)
		{
			cp w=(cp){1.0,0};int mid=m>>1;
			F(j,0,mid-1)
			{
				cp u=x[i+j],v=x[i+j+mid]*w;
				x[i+j]=u+v;x[i+j+mid]=u-v;
				w=w*wn;
			}
		}
	}
}
int main()
{
	n=read();
	scanf("%s",s);
	F(i,0,n-1) a[i].x=s[n-1-i]-'0';
	scanf("%s",s);
	F(i,0,n-1) b[i].x=s[n-1-i]-'0';
	m=1;n=2*n-1;
	while (m<=n) m<<=1,len++;n=m;
	F(i,0,n-1)
	{
		int t=i,ret=0;
		F(j,1,len) ret<<=1,ret|=t&1,t>>=1;
		rev[i]=ret;
	}
	fft(a,n,1);fft(b,n,1);
	F(i,0,n-1) c[i]=a[i]*b[i];
	fft(c,n,-1);
	F(i,0,n-1) ans[i]=(c[i].x/n)+0.5;
	F(i,0,n-1) ans[i+1]+=ans[i]/10,ans[i]%=10;
	n++;
	while (!ans[n]&&n) n--;
	D(i,n,0) putchar(ans[i]+'0');
	return 0;
}

2.NTT

//bzoj3992
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 40000
#define mod 1004535809
using namespace std;
int n,m,num,s,mg,g,bit,inv;
int a[maxn],c[maxn],A[maxn],B[maxn],ind[maxn],rev[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline ll power(ll x,int y,int p)
{
	ll ret=1;
	for(;y;y>>=1,x=x*x%p) if (y&1) ret=ret*x%p;
	return ret;
}
inline bool get_order(int x,int m)
{
	int lim=sqrt(m),phi=m-1;
	F(i,1,lim) if (phi%i==0)
	{
		if (power(x,i,m)==1){if (i!=m-1) return false;}
		if (power(x,phi/i,m)==1){if (phi/i!=m-1) return false;}
	}
	return true;
}
inline int get_primitive_root(int x)
{
	F(i,2,x) if (get_order(i,x)) return i;
}
inline void ntt(int *a,int flag)
{
	F(i,0,(1<<bit)-1) if (rev[i]>i) swap(a[i],a[rev[i]]);
	F(i,1,bit)
	{
		int y=(1ll*flag*(mod-1)/(1<<i)+mod-1)%(mod-1);
		ll wn=power(g,y,mod);
		for(int j=0;(j<1<<bit);j+=(1<<i))
		{
			ll w=1;
			F(k,j,j+(1<<(i-1))-1)
			{
				int u=a[k],v=w*a[k+(1<<(i-1))]%mod;
				a[k]=(u+v)%mod;
				a[k+(1<<(i-1))]=((u-v)%mod+mod)%mod;
				w=w*wn%mod;
			}
		}
	}
	if (flag<0) F(i,0,(1<<bit)-1) a[i]=1ll*a[i]*inv%mod;
}
inline void convol(int *a,int *b)
{
	int len=1<<bit;
	F(i,0,len-1) c[i]=b[i];
	ntt(a,1);ntt(c,1);
	F(i,0,len-1) a[i]=(ll)a[i]*c[i]%mod;
	ntt(a,-1);
	for(int i=m-1,j=0;i<len;i++,j++) a[j]=(a[j]+a[i])%mod,a[i]=0;
}
int main()
{
	n=read();m=read();num=read();s=read();
	F(i,1,s) a[i]=read();
	mg=get_primitive_root(m);
	g=get_primitive_root(mod);
	int tmp=1;
	F(i,0,m-2){ind[tmp]=i;tmp=tmp*mg%m;}
	for(bit=0;(1<<bit)<(m-1)*2;bit++);
	inv=power(1<<bit,mod-2,mod);
	F(i,0,(1<<bit)-1) rev[i]=rev[i>>1]>>1|((i&1)<<(bit-1));
	A[0]=1;
	F(i,1,s) if (a[i]) B[ind[a[i]]]=1;
	for(;n;convol(B,B),n>>=1) if (n&1) convol(A,B);
	printf("%d\n",A[ind[num]]);
	return 0;
}

3.矩阵乘法

//poj3070 
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define mod 10000
using namespace std;
int n;
struct matrix
{
	int f[2][2];
	matrix(){memset(f,0,sizeof(f));}
	friend matrix operator *(const matrix &a,const matrix &b)
	{
		matrix c;
		F(i,0,1) F(j,0,1) F(k,0,1) c.f[i][j]=(c.f[i][j]+a.f[i][k]*b.f[k][j])%mod;
		return c;
	}
};
int main()
{
	while (scanf("%d",&n))
	{
		if (n==-1) break;
		matrix a,b;
		a.f[0][0]=a.f[0][1]=a.f[1][0]=1;a.f[1][1]=0;
		b.f[1][0]=b.f[0][1]=0;b.f[0][0]=b.f[1][1]=1;
		for(;n;n>>=1,a=a*a) if (n&1) b=b*a;
		printf("%d\n",b.f[1][0]);
	}
	return 0;
}

4.高斯消元

//bzoj3503 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
using namespace std;
int n,m,cnt;
int id[50][50],a[2000][2000],b[2000],ans[2000];
int dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void gauss(int n)
{
	F(i,1,n)
	{
		bool flag=false;
		F(j,i,n) if (a[j][i])
		{
			F(k,1,n) swap(a[i][k],a[j][k]);
			flag=true;break;
		}
		if (!flag) continue;
		F(j,i+1,n) if (a[j][i]) F(k,i,n) a[j][k]^=a[i][k];
	}
	D(i,n,1)
	{
		ans[i]=a[i][i]?b[i]:1;
		if (ans[i]) F(j,1,i-1) if (a[j][i]) b[j]^=1;
	}
}
int main()
{
	n=read();m=read();
	F(i,1,n) F(j,1,m) id[i][j]=++cnt;
	F(i,1,n) F(j,1,m) F(k,0,4)
	{
		int t1=id[i][j],t2=id[i+dx[k]][j+dy[k]];
		if (t2) a[t1][t2]=1;
	}
	gauss(cnt);
	F(i,1,n)
	{
		F(j,1,m-1) printf("%d ",ans[id[i][j]]);
		printf("%d\n",ans[id[i][m]]);
	}
	return 0;
}


算法


1.Linux环境下的对拍

//Linux对拍 
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#define F(i,j,n) for(int i=j;i<=n;i++)
using namespace std;
int main()
{
	F(i,1,100)
	{
		system("./data");
		system("./baoli");
		system("./zhengjie");
		if (system("diff output.txt output2.txt"))
		{
			cout<<"WRONG ANSWER!!  "<<i<<endl;
			break;
		}
	}
	cout<<"CONGRATULATIONS!"<<endl;
}

2.背包

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXM 100005
#define MAXN 1005
using namespace std;
int f[MAXM],n,m,a,b,c,flag;
int read()
{
	int ret=0,flag=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
	return ret*flag;
}
void ZeroOnePack(int x,int y)
{
	D(i,m,x) f[i]=max(f[i],f[i-x]+y);
}
void CompletePack(int x,int y)
{
	F(i,x,m) f[i]=max(f[i],f[i-x]+y);
}
void MultiplePack(int x,int y,int t)
{
	if (x*t>=m) CompletePack(x,y);
	else
	{
		for(int k=1;k<=t;t-=k,k<<=1) ZeroOnePack(k*x,k*y);
		if (t) ZeroOnePack(x*t,y*t);
	}
}
int main()
{
	memset(f,0,sizeof(f));
	n=read();m=read();
	F(i,1,n)
	{
		flag=read();a=read();b=read();
		if (flag==1) ZeroOnePack(a,b);
		else if (flag==2) CompletePack(a,b);
		else
		{
			c=read();
			MultiplePack(a,b,c);
		}
	}
	printf("%d\n",f[m]);
}

3.RMQ

//bzoj1636&bzoj1699 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 50005
using namespace std;
int n,q,l,r,t,f[MAXN][20],g[MAXN][20];
int read()
{
	int ret=0,flag=1;
	char ch=getchar();
	while (ch<'0'||ch>'9')
	{
		if (ch=='-') flag='-';
		ch=getchar();
	}
	while (ch>='0'&&ch<='9')
	{
		ret=ret*10+ch-'0';
		ch=getchar();
	}
	return ret*flag;
}
int main()
{
	n=read();q=read();
	F(i,1,n) f[i][0]=g[i][0]=read();
	for(int i=1;(1<<i)<=n;i++) F(j,1,n-(1<<(i-1))+1)
	{
		f[j][i]=max(f[j][i-1],f[j+(1<<(i-1))][i-1]);
		g[j][i]=min(g[j][i-1],g[j+(1<<(i-1))][i-1]);
	}
	F(i,1,q)
	{
		l=read();r=read();
		t=int(log2(r-l+1));
		printf("%d\n",max(f[l][t],f[r-(1<<t)+1][t])-min(g[l][t],g[r-(1<<t)+1][t]));
	}
}

4.LCA之ST

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 200005
using namespace std;
struct data
{
	int next,to;
}e[MAXN];
int n,m,x,y,root,cnt=0,tot=0;
int head[MAXN],d[MAXN],first[MAXN],ver[MAXN],f[MAXN][25];
bool vst[MAXN];
int read()
{
	int ret=0,flag=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
	return ret*flag;
}
void add_edge(int u,int v)
{
	e[++cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
void dfs(int x,int dep)
{
	vst[x]=true;
	ver[++tot]=x;
	d[tot]=dep;
	first[x]=tot;
	for(int i=head[x];i;i=e[i].next)
	{
		if (!vst[e[i].to])
		{
			dfs(e[i].to,dep+1);
			ver[++tot]=x;
			d[tot]=dep;
		}
	}
}
void ST()
{
	F(i,1,tot) f[i][0]=i;
	for(int i=1;(1<<i)<=tot;i++) F(j,1,tot-(1<<i)+1)
	{
		int a=f[j][i-1],b=f[j+(1<<(i-1))][i-1];
		f[j][i]=d[a]<d[b]?a:b;
	}
}
int rmq(int l,int r)
{
	int t=int(log2(r-l+1));
	int a=f[l][t],b=f[r-(1<<t)+1][t];
	return d[a]<=d[b]?a:b;
}
int lca(int u,int v)
{
	int l=first[u],r=first[v];
	if (l>r) swap(l,r);
	int p=rmq(l,r);
	return ver[p];
}
int main()
{
	memset(vst,false,sizeof(vst));
	memset(head,0,sizeof(head));
	n=read();m=read();root=read();
	F(i,1,n-1)
	{
		x=read();y=read();
		add_edge(x,y);
		add_edge(y,x);
	}
	dfs(root,1);
	ST();
	F(i,1,m)
	{
		x=read();y=read();
		printf("%d\n",lca(x,y));
	}
}

5.LCA之倍增

//poj1330 倍增法求LCA 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 10005
using namespace std;
int cnt,n,t,root,x,y,head[MAXN],d[MAXN],f[MAXN][20];
bool g[MAXN];
struct edge_type
{
	int next,to;
}e[MAXN];
int read()
{
	int ret=0,flag=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
	return ret*flag;
}
void add_edge(int u,int v)
{
	e[++cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
void dfs(int x,int dep)
{
	d[x]=dep;
	for(int i=head[x];i;i=e[i].next) dfs(e[i].to,dep+1);
}
int lca(int x,int y)
{
	if (d[x]<d[y]) swap(x,y);
	int t=int(log2(d[x]-d[y]));
	D(i,t,0) if (d[x]-(1<<i)>=d[y]) x=f[x][i];
	if (x==y) return x;
	t=int(log2(d[x]));
	D(i,t,0) if (f[x][i]!=f[y][i])
	{
		x=f[x][i];
		y=f[y][i];
	}
	return f[x][0];
}
int main()
{
	t=read();
	while (t--)
	{
		memset(head,0,sizeof(head));
		memset(g,false,sizeof(g));
		memset(f,sizeof(f),0);
		cnt=0;
		n=read();
		F(i,1,n-1)
		{
			x=read();y=read();
			f[y][0]=x;
			add_edge(x,y);
			g[y]=true;
		}
		F(i,1,n) if (!g[i])
		{
			root=i;
			break;
		}
		dfs(root,1);
		for(int j=1;(1<<j)<=n;j++) F(i,1,n) f[i][j]=f[f[i][j-1]][j-1];
		x=read();y=read();
		printf("%d\n",lca(x,y));
	}
}

6.莫队算法

//bzoj2038 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 50005
using namespace std;
int n,m;
int pos[maxn],c[maxn];
ll s[maxn],sum;
struct data{int l,r,id;ll x,y;}a[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline bool cmp(data a,data b)
{
	return pos[a.l]==pos[b.l]?a.r<b.r:a.l<b.l;
}
inline bool cmpid(data a,data b)
{
	return a.id<b.id;
}
inline void update(int p,int add)
{
	sum-=s[c[p]]*s[c[p]];
	s[c[p]]+=add;
	sum+=s[c[p]]*s[c[p]];
}
inline ll gcd(ll x,ll y)
{
	return y==0?x:gcd(y,x%y);
}
int main()
{
	n=read();m=read();
	F(i,1,n) c[i]=read();
	int block=int(sqrt(n));
	F(i,1,n) pos[i]=(i-1)/block+1;
	F(i,1,m){a[i].l=read();a[i].r=read();a[i].id=i;}
	sort(a+1,a+m+1,cmp);
	for(int i=1,l=1,r=0;i<=m;i++)
	{
		for(;r<a[i].r;r++) update(r+1,1);
		for(;r>a[i].r;r--) update(r,-1);
		for(;l<a[i].l;l++) update(l,-1);
		for(;l>a[i].l;l--) update(l-1,1);
		if (a[i].l==a[i].r)
		{
			a[i].x=0;a[i].y=1;
			continue;
		}
		a[i].x=sum-(a[i].r-a[i].l+1);
		a[i].y=(ll)(a[i].r-a[i].l+1)*(a[i].r-a[i].l);
		ll tmp=gcd(a[i].y,a[i].x);
		a[i].x/=tmp;a[i].y/=tmp;
	}
	sort(a+1,a+m+1,cmpid);
	F(i,1,m) printf("%lld/%lld\n",a[i].x,a[i].y);
	return 0;
}

7.树的点分治

//poj1741
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 10005
using namespace std;
int n,k,cnt,tot,mn,root,ans;
int head[maxn],sz[maxn],mx[maxn],dis[maxn];
bool vst[maxn];
struct edge_type{int next,to,w;}e[maxn*2];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void add_edge(int x,int y,int z)
{
	e[++cnt]=(edge_type){head[x],y,z};head[x]=cnt;
	e[++cnt]=(edge_type){head[y],x,z};head[y]=cnt;
}
inline void dfssize(int x,int fa)
{
	sz[x]=1;
	mx[x]=0;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (y!=fa&&!vst[y])
		{
			dfssize(y,x);
			sz[x]+=sz[y];
			mx[x]=max(mx[x],sz[y]);
		}
	}
}
inline void dfsroot(int rt,int x,int fa)
{
	mx[x]=max(mx[x],sz[rt]-sz[x]);
	if (mx[x]<mn) mn=mx[x],root=x;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (y!=fa&&!vst[y]) dfsroot(rt,y,x);
	}
}
inline void dfsdis(int x,int d,int fa)
{
	dis[++tot]=d;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (y!=fa&&!vst[y]) dfsdis(y,d+e[i].w,x);
	}
}
inline int calc(int x,int d)
{
	int ret=0;
	tot=0;
	dfsdis(x,d,0);
	sort(dis+1,dis+tot+1);
	int i=1,j=tot;
	while (i<j)
	{
		while (dis[i]+dis[j]>k&&i<j) j--;
		ret+=j-i;
		i++;
	}
	return ret;
}
inline void dfs(int x)
{
	mn=n;
	dfssize(x,0);
	dfsroot(x,x,0);
	ans+=calc(root,0);
	vst[root]=true;
	for(int i=head[root];i;i=e[i].next)
	{
		int y=e[i].to;
		if (!vst[y])
		{
			ans-=calc(y,e[i].w);
			dfs(y);
		}
	}
}
int main()
{
	n=read();k=read();
	while (n)
	{
		memset(head,0,sizeof(head));
		memset(vst,false,sizeof(vst));
		cnt=ans=0;
		F(i,1,n-1)
		{
			int x=read(),y=read(),z=read();
			add_edge(x,y,z);
		}
		dfs(1);
		printf("%d\n",ans);
		n=read();k=read();
	}
	return 0;
}


图论


1.Dijkstra

//bzoj3931 优先队列优化的dijkstra 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<ll,int>
#define maxn 1100
#define maxm 400100
#define inf 1000000000000000ll
using namespace std;
int n,m,s,t,cnt=0;
int head[maxn],cur[maxn],x[100100],y[100100];
ll dis[maxn],c[maxn],z[100100];
ll ans=0;
bool inq[maxn],vst[maxn];
struct edge_type
{
	int to,next;
	ll v;
}e[maxm];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void add_edge(int x,int y,ll z1,ll z2)
{
	e[++cnt]=(edge_type){y,head[x],z1};head[x]=cnt;
	e[++cnt]=(edge_type){x,head[y],z2};head[y]=cnt;
}
inline void dijkstra()
{
	priority_queue<pa,vector<pa>,greater<pa> > q;
	memset(dis,-1,sizeof(dis));
	dis[1]=0;
	q.push(make_pair(0,1));
	while (!q.empty())
	{
		int x=q.top().second;q.pop();
		while (!q.empty()&&vst[x]){x=q.top().second;q.pop();}
		if (vst[x]) break;
		vst[x]=true;
		for(int i=head[x];i;i=e[i].next)
		{
			int y=e[i].to;
			if (dis[y]==-1||dis[y]>dis[x]+e[i].v)
			{
				dis[y]=dis[x]+e[i].v;
				q.push(make_pair(dis[y],y));
			}
		}
	}
}
inline ll dfs(int x,ll f)
{
	ll tmp,sum=0;
	if (x==t) return f;
	for(int &i=cur[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (e[i].v&&dis[y]==dis[x]+1)
		{
			tmp=dfs(y,min(f-sum,e[i].v));
			e[i].v-=tmp;e[i^1].v+=tmp;sum+=tmp;
			if (sum==f) return sum;
		}
	}
	if (!sum) dis[x]=-1;
	return sum;
}
inline bool bfs()
{
	queue<int> q;
	memset(dis,-1,sizeof(dis));
	dis[s]=0;q.push(s);
	while (!q.empty())
	{
		int tmp=q.front();q.pop();
		if (tmp==t) return true;
		for(int i=head[tmp];i;i=e[i].next) if (e[i].v&&dis[e[i].to]==-1)
		{
			dis[e[i].to]=dis[tmp]+1;
			q.push(e[i].to);
		}
	}
	return false;
}
inline void dinic()
{
	while (bfs())
	{
		F(i,1,t) cur[i]=head[i];
		ans+=dfs(s,inf);
	}
}
int main()
{
	n=read();m=read();
	F(i,1,m)
	{
		x[i]=read();y[i]=read();z[i]=read();
		add_edge(x[i],y[i],z[i],z[i]);
	}
	F(i,1,n) c[i]=read();
	c[1]=c[n]=inf;
	dijkstra();
	memset(head,0,sizeof(head));
	cnt=1;s=1;t=2*n;
	F(i,1,n) add_edge(i,i+n,c[i],0);
	F(i,1,m)
	{
		if (dis[y[i]]==dis[x[i]]+z[i]) add_edge(x[i]+n,y[i],inf,0);
		if (dis[x[i]]==dis[y[i]]+z[i]) add_edge(y[i]+n,x[i],inf,0);
	}
	dinic();
	printf("%lld\n",ans);
}

2.SPFA

//bzoj3007 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 3005
using namespace std;
int n,nx,ny,s,t;
double ans,dis[maxn],g[maxn][maxn];
bool inq[maxn];
struct data{int x,y;}a[maxn];
const double inf=1e10;
queue<int> q;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline double getdis(data a,data b)
{
	double x=a.x-b.x,y=a.y-b.y;
	return sqrt(x*x+y*y);
}
inline void spfa()
{
	F(i,1,t) dis[i]=inf;
	dis[s]=0;inq[s]=true;q.push(s);
	while (!q.empty())
	{
		int x=q.front();q.pop();inq[x]=false;
		F(i,1,t) if (x!=i&&max(dis[x],g[x][i])<dis[i])
		{
			dis[i]=max(dis[x],g[x][i]);
			if (!inq[i]) inq[i]=true,q.push(i);
		}
	}
}
int main()
{
	n=read();nx=read();ny=read();
	s=n+1;t=n+2;
	F(i,1,n) a[i].x=read(),a[i].y=read();
	F(i,1,n) g[s][i]=g[i][s]=min(a[i].x-1,ny-a[i].y),g[i][t]=g[t][i]=min(a[i].y-1,nx-a[i].x);
	F(i,1,n) F(j,i,n) g[i][j]=g[j][i]=getdis(a[i],a[j])/2;
	ans=inf;
	F(i,1,n) ans=min(ans,getdis(a[i],(data){1,1})),ans=min(ans,getdis(a[i],(data){nx,ny}));
	g[s][t]=g[t][s]=min(nx-1,ny-1);
	spfa();
	ans=min(ans,dis[t]);
	printf("%.2lf\n",ans);
}

3.Prim

//bzoj3479 优先队列优化的Prim 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 2005
#define INF 1000000005
using namespace std;
struct data
{
	int x,y;
}a[MAXN];
struct edge_type
{
	int to,next,w;
}e[MAXN*MAXN];
int n,c,cnt=0,ans=0,sum=0,head[MAXN],dis[MAXN];
bool vst[MAXN];
priority_queue<pa,vector<pa>,greater<pa> > q;
void add_edge(int u,int v,int w)
{
	e[++cnt].to=v;
	e[cnt].w=w;
	e[cnt].next=head[u];
	head[u]=cnt;
}
int read()
{
	int ret=0,flag=1;
	char ch=getchar();
	while (ch<'0'||ch>'9')
	{
		if (ch=='-') flag=-1;
		ch=getchar();
	}
	while (ch>='0'&&ch<='9')
	{
		ret=ret*10+ch-'0';
		ch=getchar();
	}
	return ret*flag;
}
void prim()
{
	memset(vst,false,sizeof(vst));
	F(i,0,n) dis[i]=INF;
	dis[1]=0;
	q.push(make_pair(0,1));
	while (!q.empty())
	{
		int tmp=q.top().second;
		q.pop();
		if (vst[tmp]) continue;
		vst[tmp]=true;
		ans+=dis[tmp];
		sum++;
		for(int i=head[tmp];i;i=e[i].next)
		{
			int to=e[i].to;
			if (!vst[to]&&dis[to]>e[i].w)
			{
				dis[to]=e[i].w;
				q.push(make_pair(dis[to],to));
			}
		}
	}
}
int main()
{
	n=read();c=read();
	F(i,1,n)
	{
		a[i].x=read();a[i].y=read();
	}
	F(i,1,n-1) F(j,i+1,n)
	{
		int tmp=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
		if (tmp>=c)
		{
			add_edge(i,j,tmp);
			add_edge(j,i,tmp);
		}
	}
	prim();
	if (sum==n) printf("%d\n",ans);
	else puts("-1");
}

4.Kruskal

//bzoj 1626 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 1005
using namespace std;
int n,m,u,v,cnt=0,p[MAXN];
LL x[MAXN],y[MAXN];
double ans=0;
struct data
{
	int x,y; double w;
}a[MAXN*MAXN];
LL read()
{
	LL ret=0,flag=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
	return ret*flag;
}
int find(int tmp)
{
	if (p[tmp]==tmp) return tmp;
	p[tmp]=find(p[tmp]);
	return p[tmp];
}
void merge(int a,int b)
{
	int fa=find(a),fb=find(b);
	if (fa!=fb) p[fa]=fb;
}
bool cmp(data d1,data d2)
{
	return d1.w<d2.w;
}
int main()
{
	scanf("%d%d",&n,&m);
	F(i,1,n){x[i]=read();y[i]=read();}
	F(i,1,n) p[i]=i;
	F(i,1,m)
	{
		scanf("%d%d",&u,&v);
		merge(u,v);
	}
	F(i,1,n) F(j,1,n)
	{
		if (i==j) continue;
		a[++cnt]=(data){i,j,sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))};
	}
	sort (a+1,a+cnt+1,cmp);
	F(i,1,cnt)
	{
		if (find(a[i].x)==find(a[i].y)) continue;
		merge(a[i].x,a[i].y);
		ans+=a[i].w;
	}
	printf("%.2lf\n",ans);
}

5.拓扑排序

//bzoj4010
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 100005
using namespace std;
struct edge{int next,to;}e[maxn];
int t,n,m,cnt,tot;
int d[maxn],ans[maxn],head[maxn];
priority_queue<int> q;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void add_edge(int x,int y)
{
	e[++cnt]=(edge){head[x],y};head[x]=cnt;
}
int main()
{
	t=read();
	while (t--)
	{
		n=read();m=read();
		cnt=tot=0;
		memset(head,0,sizeof(head));
		memset(d,0,sizeof(d));
		F(i,1,m)
		{
			int x=read(),y=read();
			add_edge(y,x);
			d[x]++;
		}
		F(i,1,n) if (!d[i]) q.push(i);
		while (!q.empty())
		{
			int x=q.top();q.pop();
			ans[++tot]=x;
			for(int i=head[x];i;i=e[i].next)
			{
				int y=e[i].to;
				d[y]--;
				if (!d[y]) q.push(y);
			}
		}
		if (tot==n)
		{
			D(i,n,1) printf("%d ",ans[i]);
			printf("\n");
		}
		else printf("Impossible!\n");
	}
}

6.匈牙利算法

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 1005
#define MAXM 100005
using namespace std;
int n,m,k,x,y,cnt=0,ans=0,match[MAXN],head[MAXN];
bool vst[MAXN];
struct edge_type
{
	int next,to;
}e[MAXM];
int read()
{
	int ret=0,flag=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
	return ret*flag;
}
void add_edge(int u,int v)
{
	e[++cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
bool dfs(int x)
{
	for(int i=head[x];i;i=e[i].next) if (!vst[e[i].to])
	{
		vst[e[i].to]=true;//修改访问标记  
		if (!match[e[i].to]||dfs(match[e[i].to]))
		{
			match[e[i].to]=x;
			return true;
		}
	}
	return false;
}
int main()
{
	memset(head,0,sizeof(head));
	memset(match,0,sizeof(match));
	n=read();m=read();k=read();
	F(i,1,k)
	{
		x=read();y=read();
		add_edge(x,y);
	}
	F(i,1,n)
	{
		memset(vst,false,sizeof(vst));//注意每次DFS前都要初始化  
		if (dfs(i)) ans++;
	}
	printf("%d\n",ans);
}

7.Tarjan

//bzoj1051
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<stack>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 10005
#define maxm 50005
using namespace std;
struct edge{int next,to;}e[maxm],d[maxm];
int n,m,cnt,scc,top,ans;
int h[maxn],s[maxn],sz[maxn],dfn[maxn],low[maxn],head[maxn],belong[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void dfs(int x)
{
	int tmp=0;
	low[x]=dfn[x]=++cnt;
	s[++top]=x;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (!dfn[y])
		{
			dfs(y);
			low[x]=min(low[x],low[y]);
		}
		else if (!belong[y]) low[x]=min(low[x],dfn[y]);
	}
	if (low[x]==dfn[x])
	{
		scc++;
		while (tmp!=x)
		{
			tmp=s[top--];
			belong[tmp]=scc;
			sz[scc]++;
		}
	}
}
inline void rebuild()
{
	cnt=0;
	F(i,1,n) for(int j=head[i];j;j=e[j].next)
	{
		int x=belong[i],y=belong[e[j].to];
		if (x!=y)
		{
			d[++cnt]=(edge){h[x],y};
			h[x]=cnt;
		}
	}
}
int main()
{
	n=read();m=read();
	F(i,1,m)
	{
		int x=read(),y=read();
		e[i]=(edge){head[x],y};
		head[x]=i;
	}
	F(i,1,n) if (!dfn[i]) dfs(i);
	rebuild();
	F(i,1,scc) if (!h[i])
	{
		if (ans){ans=0;break;}
		else ans=sz[i];
	}
	printf("%d\n",ans);
}


网络流


1.Dinic

//bzoj 3504 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 100
#define maxm 3000
#define inf 1000000000
using namespace std;
int n,a1,a2,an,b1,b2,bn,s,t,cnt,ans;
int head[maxn],cur[maxn],dis[maxn];
char ch[maxn][maxn];
struct edge_type{int next,to,v;}e[maxm];
inline void add_edge(int x,int y,int v1,int v2)
{
	e[++cnt]=(edge_type){head[x],y,v1};head[x]=cnt;
	e[++cnt]=(edge_type){head[y],x,v2};head[y]=cnt;
}
inline void build()
{
	memset(head,0,sizeof(head));
	cnt=1;
	F(i,1,n-1)
	{
		F(j,i+1,n)
		{
			if (ch[i][j]=='O') add_edge(i,j,2,2);
			else if (ch[i][j]=='N') add_edge(i,j,inf,inf);
		}
	}
}
inline bool bfs()
{
	queue<int> q;
	memset(dis,-1,sizeof(dis));
	dis[s]=0;q.push(s);
	while (!q.empty())
	{
		int x=q.front();q.pop();
		if (x==t) return true;
		for(int i=head[x];i;i=e[i].next)
		{
			int y=e[i].to;
			if (e[i].v&&dis[y]==-1)
			{
				dis[y]=dis[x]+1;
				q.push(y);
			}
		}
	}
	return false;
}
inline int dfs(int x,int f)
{
	int tmp,sum=0;
	if (x==t) return f;
	for(int &i=cur[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if (e[i].v&&dis[y]==dis[x]+1)
		{
			tmp=dfs(y,min(e[i].v,f-sum));
			sum+=tmp;e[i].v-=tmp;e[i^1].v+=tmp;
			if (f==sum) return sum;
		}
	}
	if (!sum) dis[x]=-1;
	return sum;
}
inline void dinic()
{
	ans=0;
	while (bfs())
	{
		F(i,1,t) cur[i]=head[i];
		ans+=dfs(s,inf);
	}
}
int main()
{
	while (scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF)
	{
		a1++;a2++;b1++;b2++;an*=2;bn*=2;
		F(i,1,n) scanf("%s",ch[i]+1);
		s=n+1;t=n+2;
		build();
		add_edge(s,a1,an,0);add_edge(a2,t,an,0);
		add_edge(s,b1,bn,0);add_edge(b2,t,bn,0);
		dinic();
		if (ans!=an+bn){puts("No");continue;}
		build();
		add_edge(s,a1,an,0);add_edge(a2,t,an,0);
		add_edge(s,b2,bn,0);add_edge(b1,t,bn,0);
		dinic();
		if (ans!=an+bn){puts("No");continue;}
		puts("Yes");
	}
}

2.最小费用最大流

//bzoj3171
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define INF 1000000000
using namespace std;
struct edge_type
{
	int next,from,to,f,c;
}e[20500];
int r,c,x,y,xx,yy,cnt=1,s,t,ans,dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
int dis[500],f[500][500],head[500],pre[500];
bool inq[500];
char ch;
queue<int>q;
void add_edge(int a,int b,int flow,int cost)
{
	e[++cnt]=(edge_type){head[a],a,b,flow,cost};head[a]=cnt;
	e[++cnt]=(edge_type){head[b],b,a,0,-cost};head[b]=cnt;
}
bool spfa()
{
	memset(inq,false,sizeof(inq));
	F(i,0,499) dis[i]=INF;
	dis[s]=0;
	inq[s]=true;
	q.push(s);
	while (!q.empty())
	{
		int tmp=q.front();
		q.pop();
		inq[tmp]=false;
		for (int p=head[tmp];p;p=e[p].next)
		{
			if (e[p].f&&dis[tmp]+e[p].c<dis[e[p].to])
			{
				dis[e[p].to]=dis[tmp]+e[p].c;
				pre[e[p].to]=p;
				if (!inq[e[p].to])
				{
					q.push(e[p].to);
					inq[e[p].to]=true;
				}
			}
		}
	}
	return dis[t]!=INF;
}
int main()
{
	ans=0;
	memset(head,0,sizeof(head));
	F(i,0,249) F(j,0,249) f[i][j]=1;
	scanf("%d%d",&r,&c);
	F(i,0,r-1) 
	{
		F(j,0,c-1)
		{
			ch=getchar();
			while (ch!='L'&&ch!='R'&&ch!='U'&&ch!='D') ch=getchar();
			if (ch=='L'){x=i;y=j-1;}
			if (ch=='R'){x=i;y=j+1;}
			if (ch=='U'){x=i-1;y=j;}
			if (ch=='D'){x=i+1;y=j;}
			x=(x+r)%r;
			y=(y+c)%c;
			f[i*c+j][x*c+y]=0;
			F(k,0,3)
			{
				xx=(i+dx[k]+r)%r;
				yy=(j+dy[k]+c)%c;
				add_edge(i*c+j,xx*c+yy+r*c,1,f[i*c+j][xx*c+yy]);
			}
		}
	}
	s=498;
	t=499;
	F(i,0,r*c-1)
	{
		add_edge(s,i,1,0);
		add_edge(i+r*c,t,1,0);
	}
	while (spfa())
	{
		int mf=INF;
		for(int p=pre[t];p;p=pre[e[p].from]) mf=min(mf,e[p].f);
		ans+=mf*dis[t];
		for(int p=pre[t];p;p=pre[e[p].from])
		{
			e[p].f-=mf;
			e[p^1].f+=mf;
		}
	}
	printf("%d\n",ans);
}


字符串


1.哈希

//bzoj1524 哈希+Trie 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define ull unsigned long long
#define maxn 2000005
#define base 233
using namespace std;
int n,tot=1;
int l[maxn],cnt[maxn],num[maxn],t[maxn][26];
ll ans;
ull ha[maxn],p[maxn];
char ch[maxn];
string s[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int main()
{
	p[0]=1;F(i,1,2000000) p[i]=p[i-1]*base;
	n=read();
	F(i,1,n)
	{
		l[i]=read();
		scanf("%s",ch);s[i]=ch; //字符串这样读入更快 
//		cin>>s[i]; //TLE
		int now=1;ull tmp=0;
		F(j,0,l[i]-1)
		{
			int x=s[i][j]-'a';
			if (!t[now][x]) t[now][x]=++tot;
			now=t[now][x];
			tmp=tmp*base+(ull)(x+1);
		}
		cnt[now]++;num[now]=i;ha[i]=tmp;
	}
	F(i,1,n)
	{
		int now=1;
		F(j,0,l[i]-1)
		{
			now=t[now][s[i][j]-'a'];
			if (cnt[now]&&ha[num[now]]*p[l[i]]+ha[i]==ha[i]*p[l[num[now]]]+ha[num[now]]) ans+=cnt[now];
		}
	}
	ans=ans*2-n;
	printf("%lld\n",ans);
	return 0;
}

2.KMP

//bzoj3461
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define maxn 1000100
char s[maxn],p[maxn];
int nxt[maxn],ls,lp,t,ans;
inline void getnext()
{
	int i=0,j=-1;
	nxt[0]=-1;
	while (i!=lp)
	{
		if (j==-1||p[i]==p[j]) nxt[++i]=++j;
		else j=nxt[j];
	}
}
inline void kmp()
{
	int i=0,j=0;ans=0;
	while (i!=ls)
	{
		if (s[i]==p[j]||j==-1) ++i,++j;
		else j=nxt[j];
		if (j==lp)
		{
			ans++;
			j=nxt[j];
		}
	}
}
int main()
{
	scanf("%d",&t);
	while (t--)
	{
		scanf("%s%s",p,s);
		ls=strlen(s);lp=strlen(p);
		getnext();
		kmp();
		printf("%d\n",ans);
	}
	return 0;
}

3.AC自动机

//bzoj3530
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define maxn 1510
#define mod 1000000007
using namespace std;
int t[maxn][10],go[maxn],f[1210][maxn][2],a[maxn];
int tot=1,n,l,ans=0;
char s[maxn];
bool v[maxn];
queue<int> q;
inline void insert()
{
	scanf("%s",s);
	int len=strlen(s),now=1;
	F(i,0,len-1)
	{
		int x=s[i]-'0';
		if (!t[now][x]) t[now][x]=++tot;
		now=t[now][x];
	}
	v[now]=1;
}
inline void bfs()
{
	q.push(1);
	while (!q.empty())
	{
		int x=q.front(),y,j;q.pop();v[x]|=v[go[x]];
		F(i,0,9)
		{
			j=go[x];
			while (j&&!t[j][i]) j=go[j];
			if (t[x][i])
			{
				go[y=t[x][i]]=j?t[j][i]:1;
				q.push(y);
			}
			else t[x][i]=j?t[j][i]:1;
		}
	}
}
int main()
{
	scanf("%s",s);
	l=strlen(s);
	F(i,0,l-1) a[i]=s[i]-'0';
	scanf("%d",&n);
	F(i,1,n) insert();
	bfs();
	memset(f,0,sizeof(f));
	F(i,1,9) if (!v[t[1][i]]) f[1][t[1][i]][0]+=1;
	F(i,1,l-2) F(j,1,tot) F(x,0,9) if (!v[t[j][x]])
		(f[i+1][t[j][x]][0]+=f[i][j][0])%=mod;
	F(i,1,l-1) F(j,1,tot) (ans+=f[i][j][0])%=mod;
	memset(f,0,sizeof(f));
	F(i,1,a[0]) if (!v[t[1][i]]) f[1][t[1][i]][i==a[0]]+=1;
	F(i,1,l-1) F(j,1,tot) F(x,0,9) if (!v[t[j][x]])
	{
		(f[i+1][t[j][x]][0]+=f[i][j][0])%=mod;
		if (x<a[i]) (f[i+1][t[j][x]][0]+=f[i][j][1])%=mod;
		else if (x==a[i]) (f[i+1][t[j][x]][1]+=f[i][j][1])%=mod;
	}
	F(i,1,tot)
	{
		(ans+=f[l][i][0])%=mod;
		(ans+=f[l][i][1])%=mod;
	}
	printf("%d\n",ans);
}

4.后缀数组

//bzoj1692
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define maxn 60100
#define inf 1000000000
using namespace std;
int a[maxn],x[maxn],y[maxn],c[maxn],sa[maxn],rank[maxn];
int n,l,r,tot,cnt=0;
char ch;
inline void build_sa(int n,int m)
{
	memset(c,0,sizeof(c));
	F(i,0,n-1) c[x[i]=a[i]]++;
	F(i,1,m-1) c[i]+=c[i-1];
	D(i,n-1,0) sa[--c[x[i]]]=i;//初始化 
	for(int k=1;k<=n;k<<=1)
	{
		int p=0;
		F(i,n-k,n-1) y[p++]=i;
		F(i,0,n-1) if (sa[i]>=k) y[p++]=sa[i]-k;//根据第二关键字排序 
		memset(c,0,sizeof(c));
		F(i,0,n-1) c[x[y[i]]]++;
		F(i,1,m-1) c[i]+=c[i-1];
		D(i,n-1,0) sa[--c[x[y[i]]]]=y[i];//根据第一关键字排序 
		swap(x,y);
		p=1;x[sa[0]]=0;
		F(i,1,n-1) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
		if (p>=n) break;
		m=p;
	}
}
int main()
{
	scanf("%d",&n);
	tot=2*n+1;
	F(i,0,n-1)
	{
		ch=getchar();
		while (ch<'A'||ch>'Z') ch=getchar();
		a[i]=ch-'A'+1;
	}
	a[n]=0;a[tot]=0;
	F(i,1,n) a[n+i]=a[n-i];
	build_sa(tot,27);
	F(i,0,tot-1) rank[sa[i]]=i;
	l=0;r=n-1;
	while (l<=r)
	{
		if (rank[l]<rank[2*n-r]) printf("%c",a[l++]+'A'-1);
		else printf("%c",a[r--]+'A'-1);
		cnt++;
		if (cnt%80==0) printf("\n");
	}
	if (cnt%80==0) printf("\n");
}

5.后缀自动机

//bzoj 3998
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 500005
#define maxm 1000005
using namespace std;
int n,t,k;
char s[maxn];
struct sam
{
    int last,cnt;
    int next[maxm][26],fa[maxm],mx[maxm],val[maxm],sum[maxm],v[maxn],q[maxm];
    sam(){last=++cnt;}
    void add(int c)
    {
        int p=last,np=last=++cnt;
        mx[np]=mx[p]+1;val[np]=1;
        while (!next[p][c]&&p) next[p][c]=np,p=fa[p];
        if (!p) fa[np]=1;
        else
        {
            int q=next[p][c];
            if (mx[p]+1==mx[q]) fa[np]=q;
            else
            {
                int nq=++cnt;mx[nq]=mx[p]+1;
                memcpy(next[nq],next[q],sizeof(next[q]));
                fa[nq]=fa[q];fa[np]=fa[q]=nq;
                while (next[p][c]==q) next[p][c]=nq,p=fa[p];
            }
        }
    }
    void pre()
    {
        F(i,1,cnt) v[mx[i]]++;
        F(i,1,n) v[i]+=v[i-1];
        D(i,cnt,1) q[v[mx[i]]--]=i;//q数组保存按mx排序的编号 
        D(i,cnt,1)
        {
            int tmp=q[i];
            if (t==1) val[fa[tmp]]+=val[tmp];
            else val[tmp]=1;
        }//val表示Right集合的大小 
        val[1]=0;
        D(i,cnt,1)
        {
            int tmp=q[i];
            sum[tmp]=val[tmp];
            F(j,0,25) sum[tmp]+=sum[next[tmp][j]];
        }//sum表示从该点出发往下走的子串个数 
    }
    void dfs(int x,int k)
    {
        if (k<=val[x]) return;//注意返回条件 
        k-=val[x];
        F(i,0,25) if (next[x][i])
        {
            int tmp=next[x][i];
            if (k<=sum[tmp])
            {
                putchar(i+'a');
                dfs(tmp,k);
                return;//注意这里的return 
            }
            k-=sum[tmp];
        }
    }
}a;
int main()
{
    scanf("%s",s+1);
    scanf("%d%d",&t,&k);
    n=strlen(s+1);
    F(i,1,n) a.add(s[i]-'a');
    a.pre();
    if (k>a.sum[1]) puts("-1");
    else a.dfs(1,k);
    return 0;
}

6.manacher

//bzoj3676 后缀数组+manacher 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define ull unsigned long long
#define maxn 600005
#define inf 1000000000
using namespace std;
int n,a[maxn],c[maxn],x[maxn],y[maxn],sa[maxn],rnk[maxn],h[maxn],p[maxn],f[maxn][20],lg2[maxn];
ll ans;
char s[maxn];
inline void build_sa(int n,int m)
{
	memset(c,0,sizeof(c));
	F(i,1,n) c[x[i]=a[i]]++;
	F(i,2,m) c[i]+=c[i-1];
	D(i,n,1) sa[c[x[i]]--]=i;
	for(int k=1;k<=n;k<<=1)
	{
		int p=0;
		F(i,n-k+1,n) y[++p]=i;
		F(i,1,n) if (sa[i]>k) y[++p]=sa[i]-k;
		memset(c,0,sizeof(c));
		F(i,1,n) c[x[y[i]]]++;
		F(i,2,m) c[i]+=c[i-1];
		D(i,n,1) sa[c[x[y[i]]]--]=y[i];
		swap(x,y);
		p=1;x[sa[1]]=1;
		F(i,2,n) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p;
		if (p>=n) break;
		m=p;
	}
}
inline void get_h()
{
	int tmp=0;
	F(i,1,n) rnk[sa[i]]=i;
	F(i,1,n)
	{
		if (tmp) tmp--;
		int j=sa[rnk[i]-1];
		while (s[i+tmp]==s[j+tmp]) tmp++;
		h[rnk[i]]=tmp;
	}
}
inline int rmq(int l,int r)
{
	if (l>r) return inf;
	int t=lg2[r-l+1];
	return min(f[l][t],f[r-(1<<t)+1][t]);
}
inline void calc(int x,int y)
{
	x=(x+1)>>1;y>>=1;
	int pos=rnk[x],len=y-x+1;
	int l,r,mid,p1=pos,p2=pos;
	l=1;r=pos;
	while (l<=r)
	{
		mid=(l+r)>>1;
		if (rmq(mid+1,pos)>=len) p1=mid,r=mid-1;
		else l=mid+1;
	}
	l=pos;r=n;
	while (l<=r)
	{
		mid=(l+r)>>1;
		if (rmq(pos+1,mid)>=len) p2=mid,l=mid+1;
		else r=mid-1;
	}
	ans=max(ans,(ll)len*(p2-p1+1));
}
inline void manacher()
{
	int mx=0,id=0;
	F(i,1,n)
	{
		if (mx>i) p[i]=min(p[id*2-i],mx-i+1);
		else p[i]=1;
		while (s[i+p[i]]==s[i-p[i]])
		{
			if (i+p[i]>mx) calc(i-p[i],i+p[i]);
			p[i]++;
		}
		if (i+p[i]-1>mx) mx=i+p[i]-1,id=i;
	}
}
int main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	F(i,1,n) a[i]=s[i]-'a'+1;
	build_sa(n,26);
	get_h();
	F(i,2,n) lg2[i]=lg2[i>>1]+1;
	F(i,1,n) f[i][0]=h[i];
	for(int j=1;(1<<j)<=n;j++) F(i,1,n-(1<<j)+1) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
	s[0]='$';s[1]='#';s[(n+1)<<1]='%';
	F(i,1,n) s[i<<1]=a[i]+'a'-1,s[i<<1|1]='#';
	n=n<<1|1;
	manacher();
	printf("%lld\n",ans);
}

7.回文自动机

//bzoj3676
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 300005
using namespace std;
int n;
ll ans;
struct pam
{
	int cnt,last;
	int next[maxn][26],fail[maxn],l[maxn],size[maxn];
	char ch[maxn];
	pam(){cnt=1;fail[0]=fail[1]=1;l[1]=-1;}
	void add(int c,int n)
	{
		int p=last;
		while (ch[n-l[p]-1]!=ch[n]) p=fail[p];
		if (!next[p][c])
		{
			int now=++cnt,tmp=fail[p];
			l[now]=l[p]+2;
			while (ch[n-l[tmp]-1]!=ch[n]) tmp=fail[tmp];
			fail[now]=next[tmp][c];next[p][c]=now;
		}
		last=next[p][c];size[last]++;
	}
	void count()
	{
		D(i,cnt,1)
		{
			size[fail[i]]+=size[i];
			ans=max(ans,(ll)size[i]*l[i]);
		}
	}
}p;
int main()
{
	scanf("%s",p.ch+1);
	n=strlen(p.ch+1);
	F(i,1,n) p.add(p.ch[i]-'a',i);
	p.count();
	printf("%lld\n",ans);
	return 0;
}


【未完待续...】

你可能感兴趣的:(我的模板库)