我的模板库

写在前面的话:

人生中总会有一些惊喜,它会给予坚守的人们以奖励,提醒着人们,生命中不光是辛劳和付出。

很多收获,最后看来,往往都是因为当初的那一点坚持。

—— 雷宇《现场》       



计算几何


1.凸包

//bzoj1670 
#include
#include
#include
#include
#include
#include
#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)=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
#include
#include
#include
#include
#include
#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)0;
}
inline void solve()
{
	int t=1;
	F(i,2,n) if (p[i].y1&&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
#include
#include
#include
#include
#include
#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.angleeps;
}
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

4.最小圆覆盖

//bzoj1336 随机增量法求最小圆覆盖 
#include
#include
#include
#include
#include
#include
#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.xr+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;
}


5.平面图转对偶图

//bzoj4541
#include
#include
#include
#include
#include
#include
#include
#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 N 200005
#define M 600005
using namespace std;
int n,m,k,cnt=1,tot,rt;
int nxt[N*6],num[N*6],q[N],fa[N*2];
ll ans1,ans2;
ll s[N*2],s2[N*2];
bool vst[N*2],flg[N*6];
struct P
{
	ll x,y;
	friend P operator +(const P &a,const P &b){return (P){a.x+b.x,a.y+b.y};}
	friend P operator -(const P &a,const P &b){return (P){a.x-b.x,a.y-b.y};}
	friend ll operator *(const P &a,const P &b){return a.x*b.y-a.y*b.x;}
}p[N];
struct edge
{
	int x,y,id;double angle;
	edge(int xx=0,int yy=0,int idd=0)
	{
		x=xx;y=yy;id=idd;
		angle=atan2((double)(p[y].y-p[x].y),(double)(p[y].x-p[x].x));
	}
	friend bool operator <(const edge &a,const edge &b){return a.angle E[N],G[N*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 int find(int x,const edge &tmp)
{
	return lower_bound(E[x].begin(),E[x].end(),tmp)-E[x].begin();
}
inline ll gcd(ll x,ll y)
{
	return y?gcd(y,x%y):x;
}
void solve()//平面图转对偶图 
{
	int now,tmp,st;ll area;
	F(i,2,cnt) if (!num[i])
	{
		area=0;now=i;st=e[i].x;num[i]=++tot;
		while (1)
		{
			int tmp=nxt[now];num[tmp]=tot;
			if (e[tmp].y==st) break;
			area+=(p[e[tmp].x]-p[st])*(p[e[tmp].y]-p[st]);
			now=tmp;
		}
		s[tot]=area;s2[tot]=area*area;
		if (area<=0) rt=tot;
	}
	F(i,2,cnt) G[num[i]].push_back(edge(num[i],num[i^1],i));
}
void dfs(int x)
{
	vst[x]=true;
	F(i,0,(int)G[x].size()-1)
	{
		int y=G[x][i].y;
		if (vst[y]) continue;
		fa[y]=x;
		flg[G[x][i].id]=flg[G[x][i].id^1]=true;
		dfs(y);
		s[x]+=s[y];s2[x]+=s2[y];
	}
}
int main()
{
	n=read();m=read();k=read();
	F(i,1,n) p[i].x=read(),p[i].y=read();
	F(i,1,m)
	{
		int x=read(),y=read();
		cnt++;e[cnt]=edge(x,y,cnt);E[x].push_back(e[cnt]);
		cnt++;e[cnt]=edge(y,x,cnt);E[y].push_back(e[cnt]);
	}
	F(i,1,n) sort(E[i].begin(),E[i].end());
	F(i,2,cnt)
	{
		int tmp=find(e[i].y,e[i^1])-1;
		if (tmp<0) tmp+=E[e[i].y].size();
		nxt[i]=E[e[i].y][tmp].id;
	}
	solve();
	dfs(rt);
	F(i,1,k)
	{
		int tot=(read()+ans2)%n+1;
		F(j,1,tot) q[j]=(read()+ans2)%n+1;
		ans1=ans2=0;q[tot+1]=q[1];
		F(j,1,tot)
		{
			int x=q[j],y=q[j+1],tmp=E[x][find(x,edge(x,y,0))].id;
			if (!flg[tmp]) continue;
			if (num[tmp]==fa[num[tmp^1]]) ans1+=s[num[tmp^1]],ans2+=s2[num[tmp^1]];
			else ans1-=s[num[tmp]],ans2-=s2[num[tmp]];
		}
		if (ans1<0) ans1=-ans1,ans2=-ans2;
		ll d=gcd(ans1,ans2);ans1/=d;ans2/=d;
		if (ans2&1) ans1<<=1;else ans2>>=1;
		printf("%lld %lld\n",ans2,ans1);
	}
	return 0;
}



数据结构


1.线段树

//bzoj1798 加法乘法双标记线段树 
#include
#include
#include
#include
#include
#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&&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&&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&&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
#include
#include
#include
#include
#include
#include
#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
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.val1&&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
#include
#include
#include
#include
#include
#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
#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

4.Treap

//bzoj1208
#include
#include
#include
#include
#include
#include
#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
#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 (xx) 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 (xv[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)

5.Trie

//poj2001
#include
#include
#include
#include
#include
#include
#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
#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
#include
#include
#include
#include
#include
#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
#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]) 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
#include
#include
#include
#include
#include
#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]'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=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

8.树链剖分

//bzoj2819
#include
#include
#include
#include
#include
#include
#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[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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#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]>i)&1)^1;
		if (id[t[tmp][j]]>=l) ans|=(1<'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
#include
#include
#include
#include
#include
#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;
}


13.左偏树

//bzoj1367 左偏树 
#include
#include
#include
#include
#include
#include
#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 N 1000005
using namespace std;
int n,m,tot,a[N],rt[N],l[N],r[N];
ll ans;
struct HEAP
{
	int cnt,l[N],r[N],v[N],d[N],sz[N];
	int merge(int x,int y)
	{
		if (!x||!y) return x+y;
		if (v[x]'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int main()
{
	n=read();
	F(i,1,n) a[i]=read()-i;
	F(i,1,n)
	{
		tot++;
		rt[tot]=heap.new_heap(a[i]);
		l[tot]=r[tot]=i;
		while (tot>1&&heap.v[rt[tot-1]]>heap.v[rt[tot]])
		{
			tot--;
			rt[tot]=heap.merge(rt[tot],rt[tot+1]);
			r[tot]=r[tot+1];
			while (heap.sz[rt[tot]]>(r[tot]-l[tot]+2)/2) heap.pop(rt[tot]);
		}
	}
	F(i,1,tot)
	{
		int tmp=heap.v[rt[i]];
		F(j,l[i],r[i]) ans+=abs(a[j]-tmp);
	}
	printf("%lld\n",ans);
	return 0;
}



数学


1.FFT

//bzoj2179
#include
#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>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
#include
#include
#include
#include
#include
#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<i) swap(a[i],a[rev[i]]);
	F(i,1,bit)
	{
		int y=(1ll*flag*(mod-1)/(1<>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
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#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;
}


5.多项式求逆

//bzoj3456
#include
#include
#include
#include
#include
#include
#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 300000
#define mod 1004535809
using namespace std;
int n,rev[maxn];
ll fac[maxn],a[maxn],b[maxn],c[maxn],inv_b[maxn],tmp[maxn];
inline ll getpow(ll x,ll y)
{
    ll ret=1;
    for(;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;
    return ret;
}
void ntt(ll *a,int n,int flag)
{
    F(i,0,n-1) if (i>1;
        ll wn=getpow(3,((mod-1)/m*flag+(mod-1))%(mod-1));
        for(int i=0;i>1);
    memcpy(tmp,a,sizeof(a[0])*n);
    memset(tmp+n,0,sizeof(a[0])*n);
    int m=1,len=-1;
    while (m<(n<<1)) m<<=1,len++;
    F(i,1,m-1) rev[i]=(rev[i>>1]>>1)|((i&1)<>1]>>1)|((i&1)<



算法


1.Linux环境下的对拍

//Linux对拍 
#include
#include
#include
#include
#include
#include
#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!!  "<

2.背包

#include
#include
#include
#include
#include
#include
#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
#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
#include
#include
#include
#include
#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
#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<

4.LCA之ST

#include
#include
#include
#include
#include
#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
#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<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
#include
#include
#include
#include
#include
#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
#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]) 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<

6.莫队算法

//bzoj2038 
#include
#include
#include
#include
#include
#include
#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.ra[i].r;r--) update(r,-1);
		for(;la[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
#include
#include
#include
#include
#include
#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]k&&i


图论


1.Dijkstra

//bzoj3931 优先队列优化的dijkstra 
#include
#include
#include
#include
#include
#include
#include
#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
#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,greater > 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 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
#include
#include
#include
#include
#include
#include
#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 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])

3.Prim

//bzoj3479 优先队列优化的Prim 
#include
#include
#include
#include
#include
#include
#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
#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,greater > 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
#include
#include
#include
#include
#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
#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

5.拓扑排序

//bzoj4010
#include
#include
#include
#include
#include
#include
#include
#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 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
#include
#include
#include
#include
#include
#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
#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
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#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 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
#include
#include
#include
#include
#include
#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;
queueq;
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


字符串


1.哈希

//bzoj1524 哈希+Trie 
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#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
#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 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

4.后缀数组

//bzoj1692
#include
#include
#include
#include
#include
#include
#include
#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
#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]

5.后缀自动机

//bzoj 3998
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#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<>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<

7.回文自动机

//bzoj3676
#include
#include
#include
#include
#include
#include
#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;
}


【未完待续...】

你可能感兴趣的:(总结,OIer的狂欢)