我的模板库【填坑中】

字符串

  • AC自动机
  • manacher

【APIO2014】uoj103 Palindromes【2017.7.12】

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=600010;
#define LL long long
char s[maxn];
int trans[maxn][30],fail[maxn],val[maxn],cnt[maxn],ord[maxn],mxl[maxn],num[maxn],fa[maxn][20],pos[maxn],n,tot=1;
int main()
{
	//int xxx=0;
	//freopen("b.in","r",stdin);
	//freopen("b.out","w",stdout);
	LL ans=0;
	int last=1,u,nu,v,nv,x,y,lim=0,mx,id;
	scanf("%s",s+1);
	n=strlen(s+1);
	for (int i=1;i<=n;i++)
	{
		x=s[i]-'a'+1;
		u=last;
		val[last=nu=++tot]=i;
		while (u&&!trans[u][x])
		{
			trans[u][x]=nu;
			u=fail[u];
		}
		if (!u) fail[nu]=1;
		else
		{
			v=trans[u][x];
			if (val[v]==val[u]+1) fail[nu]=v;
			else
			{
				val[nv=++tot]=val[u]+1;
				fail[nv]=fail[v];
				fail[v]=fail[nu]=nv;
				for (int j=1;j<=26;j++) trans[nv][j]=trans[v][j];
				while (u&&trans[u][x]==v)
				{
					trans[u][x]=nv;
					u=fail[u];
				}
			}
		}
	}
	pos[0]=1;
	for (int i=1;i<=n;i++) num[pos[i]=trans[pos[i-1]][s[i]-'a'+1]]++;
	for (int i=1;i<=tot;i++) cnt[val[i]]++;
	for (int i=1;i<=n;i++) cnt[i]+=cnt[i-1];
	for (int i=1;i<=tot;i++) ord[cnt[val[i]]--]=i;
	for (int i=tot;i>=1;i--) num[fail[ord[i]]]+=num[ord[i]];
	while ((1<<lim)<tot) lim++;
	for (int i=1;i<=tot;i++) fa[i][0]=fail[i];
	for (int k=1;k<=lim;k++)
		for (int i=1;i<=tot;i++)
			fa[i][k]=fa[fa[i][k-1]][k-1];
	for (int i=n*2+1;i>=1;i--) s[i]=(i&1)?'$':s[i/2];
	s[0]='@';
	s[2*n+2]='%';
	mx=0;
	for (int i=1;i<=2*n+1;i++)
	{
		if (i<=mx) mxl[i]=min(mxl[2*id-i],mx-i);
		//printf("%d:%d,%d,%d\n",i,id,mx,mxl[i]);
		while (s[i-mxl[i]-1]==s[i+mxl[i]+1])
		{
			mxl[i]++;
			//xxx++;
		}
		if (i+mxl[i]>mx)
		{
			for (int j=mx;j<=i+mxl[i];j+=2)
			{
				x=j/2;
				y=(2*i-j)/2+1;
				u=pos[x];
				for (int k=lim;k>=0;k--)
					if (val[fa[u][k]]>=x-y+1) u=fa[u][k];
				ans=max(ans,(LL)num[u]*(x-y+1));
			}
			mx=i+mxl[i];
			id=i;
		}
	}
	//printf("%d\n",xxx);
	printf("%lld\n",ans);
}
  • 后缀数组
    poj1743 Musical Theme【2017.4.21】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int c=90,maxn=30010,oo=0x3f3f3f3f;
int a[maxn],sa[maxn],rank[maxn],height[maxn],f[maxn],cnt[maxn],n;
void solve()
{
	int m,p,l,r,mid,ok,mnp,mxp;
	memset(a,0,sizeof(a));
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<n;i++) a[i]=a[i+1]-a[i]+c;
	a[n]=0;
	m=190;
	for (int i=1;i<=m;i++) cnt[i]=0;
	for (int i=1;i<n;i++) cnt[rank[i]=a[i]]++;
	for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
	for (int i=n-1;i;i--) sa[cnt[a[i]]--]=i;
	for (int k=1;k<n;k<<=1)
	{
		p=0;
		for (int i=n-k;i<n;i++) f[++p]=i;
		for (int i=1;i<n;i++) if (sa[i]-k>=1) f[++p]=sa[i]-k;
		for (int i=1;i<=m;i++) cnt[i]=0;
		for (int i=1;i<n;i++) cnt[rank[f[i]]]++;
		for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
		for (int i=n-1;i;i--) sa[cnt[rank[f[i]]]--]=f[i];
		for (int i=1;i<n;i++) f[i]=rank[i];
		rank[sa[1]]=1;
		for (int i=2;i<n;i++)
			if (f[sa[i]]!=f[sa[i-1]]||f[sa[i]+k]!=f[sa[i-1]+k])
				rank[sa[i]]=rank[sa[i-1]]+1;
			else
				rank[sa[i]]=rank[sa[i-1]];
		m=rank[sa[n-1]];
		if (m>=n-1) break;
	}
	for (int i=1;i<n;i++)
	{
		height[rank[i]]=height[rank[i-1]];
		if (height[rank[i]]) height[rank[i]]--;
		while (a[i+height[rank[i]]]==a[sa[rank[i]-1]+height[rank[i]]]) height[rank[i]]++;
	}
	l=0;
	r=n-1;
	while (l<r)
	{
		mid=l+r+1>>1;
		ok=0;
		for (int i=1;i<n&&!ok;i++)
			if (height[i]>=mid)
			{
				mxp=max(mxp,sa[i]);
				mnp=min(mnp,sa[i]);
				if (mxp-mnp>mid) ok=1;
			}
			else mxp=mnp=sa[i];
		if (ok) l=mid;
		else r=mid-1;
	}
	//printf("%d\n",l+1);
	if (l>=4) printf("%d\n",l+1);
	else printf("0\n");
}
int main()
{
	while (scanf("%d",&n)&&n) solve();
}

poj2774 Long Long Message【2017.5.17】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=400010;
char s[maxn];
int sa[maxn],rank[maxn],height[maxn],f[maxn],g[maxn],cnt[maxn];
int main()
{
	int n,m=27,l,p,ans=0;
	scanf("%s",s+1);
	l=strlen(s+1);
	s[l+1]='z'+1;
	scanf("%s",s+l+2);
	n=strlen(s+1);
	for (int i=1;i<=n;i++) cnt[rank[i]=s[i]-'a'+1]++;
	for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
	for (int i=n;i;i--) sa[cnt[rank[i]]--]=i;
	for (int k=1;;k<<=1)
	{
		p=0;
		for (int i=n-k+1;i<=n;i++) f[++p]=i;
		for (int i=1;i<=n;i++)
			if (sa[i]>k) f[++p]=sa[i]-k;
		for (int i=1;i<=m;i++) cnt[i]=0;
		for (int i=1;i<=n;i++) cnt[rank[f[i]]]++;
		for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
		for (int i=n;i;i--) sa[cnt[rank[f[i]]]--]=f[i];
		for (int i=1;i<=n;i++) g[i]=rank[i];
		rank[sa[1]]=1;
		for (int i=2;i<=n;i++)
			rank[sa[i]]=rank[sa[i-1]]+(g[sa[i]]!=g[sa[i-1]]||g[sa[i]+k]!=g[sa[i-1]+k]);
		m=rank[sa[n]];
		if (m>=n) break;
	}
	for (int i=1;i<=n;i++)
	{
		height[rank[i]]=height[rank[i-1]];
		if (height[rank[i]]) height[rank[i]]--;
		while (s[i+height[rank[i]]]==s[sa[rank[i]-1]+height[rank[i]]]) height[rank[i]]++;
	}
	for (int i=2;i<=n;i++)
		if ((sa[i]<=l&&sa[i-1]>=l+2)||(sa[i]>=l+2&&sa[i-1]<=l))
			ans=max(ans,height[i]);
	printf("%d\n",ans);
}
  • 后缀自动机
    SPOJ NSUBSTR Substrings【2017.4.21】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500010;
char s[maxn];
int fail[maxn],val[maxn],trans[maxn][30],cnt[maxn],f[maxn],num[maxn],ans[maxn],
n,tot=1;
int main()
{
	int p,last=1,x,np,q,nq;
	scanf("%s",s+1);
	n=strlen(s+1);
	for (int i=1;i<=n;i++)
	{
		x=s[i]-'a';
		p=last;
		val[last=np=++tot]=val[p]+1;
		while (p&&!trans[p][x])
		{
			trans[p][x]=np;
			p=fail[p];
		}
		if (!p) fail[np]=1;
		else
		{
			q=trans[p][x];
			if (val[q]==val[p]+1) fail[np]=q;
			else
			{
				val[nq=++tot]=val[p]+1;
				fail[nq]=fail[q];
				fail[q]=fail[np]=nq;
				for (int j=0;j<26;j++) trans[nq][j]=trans[q][j];
				while (p&&trans[p][x]==q)
				{
					trans[p][x]=nq;
					p=fail[p];
				}
			}
		}
	}
	p=1;
	for (int i=1;i<=n;i++)
	{
		p=trans[p][s[i]-'a'];
		cnt[p]++;
	}
	for (int i=1;i<=tot;i++) num[val[i]]++;
	for (int i=n-1;i;i--) num[i]+=num[i+1];
	for (int i=1;i<=tot;i++) f[num[val[i]]--]=i;
	for (int i=1;i<=tot;i++)
	{
		cnt[fail[f[i]]]+=cnt[f[i]];
		ans[val[f[i]]]=max(ans[val[f[i]]],cnt[f[i]]);
	}
	for (int i=n-1;i;i--) ans[i]=max(ans[i],ans[i+1]);
	for (int i=1;i<=n;i++) printf("%d\n",ans[i]);
}

poj2774 Long Long Message【2017.5.17】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200010;
char s1[maxn],s2[maxn];
int trans[maxn][30],fail[maxn],val[maxn],
n,m,tot=1;
int main()
{
	int last=1,x,p,q,np,nq,now=0,ans=0;
	scanf("%s",s1+1);
	n=strlen(s1+1);
	for (int i=1;i<=n;i++)
	{
		x=s1[i]-'a'+1;
		p=last;
		val[last=np=++tot]=val[p]+1;
		while (p&&!trans[p][x])
		{
			trans[p][x]=np;
			p=fail[p];
		}
		if (!p) fail[np]=1;
		else
		{
			q=trans[p][x];
			if (val[q]==val[p]+1) fail[np]=q;
			else
			{
				val[nq=++tot]=val[p]+1;
				fail[nq]=fail[q];
				fail[q]=fail[np]=nq;
				for (int j=1;j<=26;j++) trans[nq][j]=trans[q][j];
				while (p&&trans[p][x]==q)
				{
					trans[p][x]=nq;
					p=fail[p];
				}
			}
		}
	}
	scanf("%s",s2+1);
	m=strlen(s2+1);
	p=1;
	for (int i=1;i<=m;i++)
	{
		x=s2[i]-'a'+1;
		if (trans[p][x])
		{
			p=trans[p][x];
			now++;
		}
		else
		{
			while (p&&!trans[p][x]) p=fail[p];
			if (p)
			{
				now=val[p]+1;
				p=trans[p][x];
			}
			else
			{
				now=0;
				p=1;
			}
		}
		ans=max(ans,now);
	}
	printf("%d\n",ans);
}
  • 回文自动机
    【APIO2014】bzoj3676 回文串
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=600010;
char s[maxn];
int val[maxn],fail[maxn],trans[maxn][30],cnt[maxn],num[maxn],f[maxn],n;
int main()
{
	int tot=1,last=0,p,np,x,q;
	LL ans=0;
	scanf("%s",s+1);
	n=strlen(s+1);
	fail[0]=fail[1]=1;
	val[1]=-1;
	for (int i=1;i<=n;i++)
	{
		x=s[i]-'a';
		p=last;
		while (s[i-val[p]-1]!=s[i]) p=fail[p];
		if (!trans[p][x])
		{
			val[np=++tot]=val[p]+2;
			q=fail[p];
			while (s[i-val[q]-1]!=s[i]) q=fail[q];
			fail[np]=trans[q][x];
			trans[p][x]=np;
		}
		cnt[last=trans[p][x]]++;
	}
	for (int i=2;i<=tot;i++) num[val[i]]++;
	for (int i=1;i<=n;i++) num[i]+=num[i-1];
	for (int i=2;i<=tot;i++) f[num[val[i]]--]=i;
	for (int i=tot-1;i;i--)
	{
		ans=max(ans,(LL)val[f[i]]*cnt[f[i]]);
		cnt[fail[f[i]]]+=cnt[f[i]];
	}
	printf("%lld\n",ans);
}

树形数据结构

  • treap
    bzoj3224 普通平衡树【2017.4.17】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010,no=2e9+100;
int rd()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9')
	{
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
struct treap
{
	int son[2][maxn],v[maxn],w[maxn],siz[maxn],cnt[maxn],rt,tot;
	void upd(int p)
	{
		siz[p]=siz[son[0][p]]+siz[son[1][p]]+cnt[p];
	}
	void rot(int &p,int fl)
	{
		int u=son[fl][p],v=son[fl^1][u];
		son[fl][p]=v;
		son[fl^1][u]=p;
		upd(p);
		p=u;
		upd(p);
	}
	void ins(int &p,int x)
	{
		if (!p)
		{
			p=++tot;
			v[p]=x;
			w[p]=rand();
			siz[p]=cnt[p]=1;
			return;
		}
		siz[p]++;
		if (v[p]==x)
		{
			cnt[p]++;
			return;
		}
		int flag=x>v[p];
		ins(son[flag][p],x);
		if (w[son[flag][p]]>w[p]) rot(p,flag);
	}
	void del(int &p,int x)
	{
		if (v[p]==x)
		{
			if (son[0][p]*son[1][p]==0)
			{
				cnt[p]--;
				siz[p]--;
				if (!cnt[p]) p=son[0][p]+son[1][p];
			}
			else
			{
				int fl=w[son[0][p]]<w[son[1][p]];
				rot(p,fl);
				siz[p]--;
				del(son[fl^1][p],x);
			}
			return;
		}
		siz[p]--;
		del(son[x>v[p]][p],x);
	}
	int rank(int p,int x)
	{
		if (v[p]==x) return siz[son[0][p]]+1;
		if (x<v[p]) return rank(son[0][p],x);
		return siz[son[0][p]]+cnt[p]+rank(son[1][p],x);
	}
	int qry(int p,int x)
	{
		if (x<=siz[son[0][p]]) return qry(son[0][p],x);
		if (x<=siz[son[0][p]]+cnt[p]) return v[p];
		return qry(son[1][p],x-(siz[son[0][p]]+cnt[p]));
	}
	int pre(int p,int x)
	{
		if (!p) return no;
		if (v[p]<x)
		{
			int y=pre(son[1][p],x);
			return y==no?v[p]:y;
		}
		return pre(son[0][p],x);
	}
	int suc(int p,int x)
	{
		if (!p) return no;
		if (v[p]>x)
		{
			int y=suc(son[0][p],x);
			return y==no?v[p]:y;
		}
		return suc(son[1][p],x);
	}
	void Ins(int x)
	{
		ins(rt,x);
	}
	void Del(int x)
	{
		del(rt,x);
	}
	int Rank(int x)
	{
		return rank(rt,x);
	}
	int Qry(int x)
	{
		return qry(rt,x);
	}
	int Pre(int x)
	{
		return pre(rt,x);
	}
	int Suc(int x)
	{
		return suc(rt,x);
	}
}t;
int main()
{
	int n,opt;
	n=rd();
	while (n--)
	{
		opt=rd();
		switch (opt)
		{
			case 1:t.Ins(rd());break;
			case 2:t.Del(rd());break;
			case 3:printf("%d\n",t.Rank(rd()));break;
			case 4:printf("%d\n",t.Qry(rd()));break;
			case 5:printf("%d\n",t.Pre(rd()));break;
			case 6:printf("%d\n",t.Suc(rd()));break;
		}
	}
}
  • splay
    bzoj3224 普通平衡树【2017.4.17】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010,no=2e9+1000;
int rd()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9')
	{
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
int fa[maxn],son[maxn][2],v[maxn],cnt[maxn],siz[maxn],
tot,rt;
void pause()
{
	int x=0;
	x=1;
}
void upd(int p)
{
	siz[p]=siz[son[p][0]]+siz[son[p][1]]+cnt[p];
}
void rot(int p,int fl)
{
	int u=son[p][fl],v=son[u][fl^1];
	fa[u]=fa[p];
	if (!fa[u]) rt=u;
	else son[fa[u]][son[fa[u]][1]==p]=u;
	son[p][fl]=v;
	if (v) fa[v]=p;
	son[u][fl^1]=p;
	fa[p]=u;
	upd(p);
	upd(u);
}
void splay(int u)
{
	int v,x,w,y;
	upd(u);
	while (rt!=u)
	{
		v=fa[u];
		x=son[v][1]==u;
		if (v==rt) rot(v,x);
		else
		{
			w=fa[v];
			y=son[w][1]==v;
			if (x==y) rot(w,y),rot(v,x);
			else rot(v,x),rot(w,y);
		}
	}
}
void ins(int p,int x,int f,int fl)
{
	if (!p)
	{
		p=++tot;
		cnt[p]=1;
		v[p]=x;
		if (f)
		{
			fa[p]=f;
			son[f][fl]=p;
		}
		else rt=p;
		splay(p);
		return;
	}
	if (x==v[p])
	{
		cnt[p]++;
		splay(p);
		return;
	}
	int fl2=x>v[p];
	ins(son[p][fl2],x,p,fl2);
}
void del(int p,int x,int f,int fl)
{
	if (v[p]==x)
	{
		if (cnt[p]>1)
		{
			cnt[p]--;
			splay(p);
		}
		else
		{
			if (son[p][0]*son[p][1]==0)
			{
				if (f)
				{
					son[f][fl]=son[p][0]+son[p][1];
					if (son[f][fl])
					{
						fa[son[f][fl]]=f;
						splay(son[f][fl]);
					}
					else splay(f);
				}
				else fa[rt=son[p][0]+son[p][1]]=0;
			}
			else
			{
				int fl2=siz[son[p][0]]<siz[son[p][1]];
				rot(p,fl2);
				del(p,x,fa[p],fl2^1);
			}
		}
	}
	else
	{
		int fl2=x>v[p];
		del(son[p][fl2],x,p,fl2);
	}
}
int rank(int p,int x)
{
	if (x==v[p])
	{
		splay(p);
		return siz[son[p][0]]+1;
	}
	if (x<v[p]) return rank(son[p][0],x);
	return rank(son[p][1],x);
}
int qry(int p,int x)
{
	if (x<=siz[son[p][0]]) return qry(son[p][0],x);
	if (x<=siz[son[p][0]]+cnt[p])
	{
		splay(p);
		return v[p];
	}
	return qry(son[p][1],x-siz[son[p][0]]-cnt[p]);
}
int pre(int p,int x)
{
	if (!p) return no;
	if (v[p]<x)
	{
		int y=pre(son[p][1],x);
		if (y==no)
		{
			splay(p);
			return v[p];
		}
		return y;
	}
	return pre(son[p][0],x);
}
int suc(int p,int x)
{
	if (!p) return no;
	if (v[p]>x)
	{
		int y=suc(son[p][0],x);
		if (y==no)
		{
			splay(p);
			return v[p];
		}
		return y;
	}
	return suc(son[p][1],x);
}
int main()
{
	/*freopen("phs.in","r",stdin);
	freopen("phs.out","w",stdout);*/
	int n,opt;
	n=rd();
	while (n--)
	{
		if (n==1) pause(); 
		opt=rd();
		switch (opt)
		{
			case 1:ins(rt,rd(),0,0);break;
			case 2:del(rt,rd(),0,0);break;
			case 3:printf("%d\n",rank(rt,rd()));break;
			case 4:printf("%d\n",qry(rt,rd()));break;
			case 5:printf("%d\n",pre(rt,rd()));break;
			case 6:printf("%d\n",suc(rt,rd()));break;
		}
	}
}

【AHOI2006】bzoj1269 文本编辑器【2017.4.19】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define rt son[1][0]
const int maxn=4000010;
char s[maxn],s1[maxn],chr[maxn];
int fa[maxn],son[maxn][2],inv[maxn],size[maxn],tot=3;
void down(int u)
{
	if (inv[u])
	{
		swap(son[u][0],son[u][1]);
		if (son[u][0]) inv[son[u][0]]^=1;
		if (son[u][1]) inv[son[u][1]]^=1;
		inv[u]=0;
	}
}
void upd(int u)
{
	size[u]=size[son[u][0]]+size[son[u][1]]+1;
}
int find(int u,int p)
{
	down(u);
	if (p<=size[son[u][0]]) return find(son[u][0],p);
	if (p==size[son[u][0]]+1) return u;
	return find(son[u][1],p-size[son[u][0]]-1);
}
void rot(int u,int f)
{
	int v=son[u][f],w=son[v][f^1],x=fa[u],fx=son[x][1]==u;
	son[u][f]=w;
	if (w) fa[w]=u;
	son[v][f^1]=u;
	fa[u]=v;
	son[x][fx]=v;
	fa[v]=x;
	upd(u);
	upd(v);
}
void get(int p,int f)
{
	int u=find(rt,p),x,y,fx,fy;
	while (fa[u]!=f)
	{
		x=fa[u];
		fx=son[x][1]==u;
		y=fa[x];
		fy=son[y][1]==x;
		if (y==f) rot(x,fx);
		else
		{
			if (fx==fy) rot(y,fy),rot(x,fx);
			else rot(x,fx),rot(y,fy);
		}
	}
}
int build(int l,int r)
{
	if (l>r) return 0;
	int mid=l+r>>1,ret;
	chr[ret=++tot]=s[mid];
	son[ret][0]=build(l,mid-1);
	if (son[ret][0]) fa[son[ret][0]]=ret;
	son[ret][1]=build(mid+1,r);
	if (son[ret][1]) fa[son[ret][1]]=ret;
	upd(ret);
	return ret;
}
int main()
{
	int m,n,p=1;
	scanf("%d",&m);
	son[1][0]=2;
	son[2][0]=3;
	fa[2]=1;
	fa[3]=2;
	size[2]=2;
	size[3]=1;
	while (m--)
	{
		scanf("%s",s1);
		switch (s1[0])
		{
			case 'M':scanf("%d",&p);p++;break;
			case 'I':
				scanf("%d",&n);
				gets(s+1);
				gets(s+1);
				get(p,1);
				get(p+1,rt);
				son[son[rt][1]][0]=build(1,n);
				fa[son[son[rt][1]][0]]=son[rt][1];
				upd(son[rt][1]);
				upd(rt);
				break;
			case 'D':
				scanf("%d",&n);
				get(p,1);
				get(p+n+1,rt);
				son[son[rt][1]][0]=0;
				upd(son[rt][1]);
				upd(rt);
				break;
			case 'R':
				scanf("%d",&n);
				get(p,1);
				get(p+n+1,rt);
				inv[son[son[rt][1]][0]]^=1;
				break;
			case 'G':
				get(p+1,1);
				printf("%c\n",chr[rt]);
				break;
			case 'P':p--;break;
			case 'N':p++;break;
		}
	}
}
  • 替罪羊树
  • kdtree
    bzoj2648 SJY摆棋子【2017.4.21】
#include<cstdio>
#include<algorithm>
using namespace std;
#define R(k) for (int k=0;k<2;k++)
const int maxn=2000010,oo=0x3f3f3f3f;
int D,ans;
struct Point
{
	int x[2];
	void rd()
	{
		R(k) scanf("%d",&x[k]);
	}
	bool operator < (const Point &p) const
	{
		return x[D]<p.x[D];
	}
}a[maxn],p;
int lson[maxn],rson[maxn],mx[maxn][2],mn[maxn][2],tot,rt;
void upd(int p)
{
	R(k)
	{
		mx[p][k]=mn[p][k]=a[p].x[k];
		if (lson[p])
		{
			mx[p][k]=max(mx[p][k],mx[lson[p]][k]);
			mn[p][k]=min(mn[p][k],mn[lson[p]][k]);
		}
		if (rson[p])
		{
			mx[p][k]=max(mx[p][k],mx[rson[p]][k]);
			mn[p][k]=min(mn[p][k],mn[rson[p]][k]);
		}
	}
}
int build(int L,int R,int d)
{
	if (L>R) return 0;
	int mid=L+R>>1;
	D=d;
	nth_element(a+L,a+mid,a+R+1);
	lson[mid]=build(L,mid-1,d^1);
	rson[mid]=build(mid+1,R,d^1);
	upd(mid);
	return mid;
}
void ins(int &u,int d)
{
	if (!u)
	{
		a[u=++tot]=p;
		R(k) mn[u][k]=mx[u][k]=p.x[k];
		return;
	}
	if (p.x[d]<a[u].x[d]) ins(lson[u],d^1);
	else ins(rson[u],d^1);
	upd(u);
}
int mindis(int u)
{
	if (!u) return oo;
	int ret=0;
	R(k)
	{
		if (mn[u][k]>p.x[k]) ret+=mn[u][k]-p.x[k];
		if (mx[u][k]<p.x[k]) ret+=p.x[k]-mx[u][k];
	}
	return ret;
}
void qry(int u,int d)
{
	int ret=0,lmn=mindis(lson[u]),rmn=mindis(rson[u]);
	R(k) ret+=abs(p.x[k]-a[u].x[k]);
	ans=min(ans,ret);
	if (lmn<rmn)
	{
		if (lmn<ans) qry(lson[u],d^1);
		if (rmn<ans) qry(rson[u],d^1);
	}
	else
	{
		if (rmn<ans) qry(rson[u],d^1);
		if (lmn<ans) qry(lson[u],d^1);
	}
}
int main()
{
	int n,m,opt;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) a[i].rd();
	rt=build(1,n,0);
	tot=n;
	while (m--)
	{
		scanf("%d",&opt);
		R(k) scanf("%d",&p.x[k]);
		if (opt==1) ins(rt,0);
		else
		{
			ans=oo;
			qry(rt,0);
			printf("%d\n",ans);
		}
	}
}
  • 左偏树
  • 主席树
    poj2104 K-th Number【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2000010;
int rd()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9')
	{
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
int a[maxn],ord[maxn],rt[maxn],sum[maxn],lson[maxn],rson[maxn],n,tot;
int modi(int bro,int L,int R,int x)
{
	int u=++tot;
	sum[tot]=sum[bro]+1;
	if (L==R) return u;
	int mid=(L+R)/2;
	if (x<=mid)
	{
		lson[u]=modi(lson[bro],L,mid,x);
		rson[u]=rson[bro];
	}
	else
	{
		lson[u]=lson[bro];
		rson[u]=modi(rson[bro],mid+1,R,x);
	}
	return u;
}
int qry(int u,int v,int L,int R,int k)
{
	if (L==R) return L;
	int mid=(L+R)/2;
	if (k<=sum[lson[u]]-sum[lson[v]]) return qry(lson[u],lson[v],L,mid,k);
	return qry(rson[u],rson[v],mid+1,R,k-(sum[lson[u]]-sum[lson[v]]));
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int m,q,l,r,k;
	n=rd();
	q=rd();
	for (int i=1;i<=n;i++) ord[i]=a[i]=rd();
	sort(ord+1,ord+n+1);
	m=unique(ord+1,ord+n+1)-ord-1;
	for (int i=1;i<=n;i++) a[i]=lower_bound(ord+1,ord+m+1,a[i])-ord;
	for (int i=1;i<=n;i++) rt[i]=modi(rt[i-1],1,m,a[i]);
	while (q--)
	{
		l=rd();
		r=rd();
		k=rd();
		printf("%d\n",ord[qry(rt[r],rt[l-1],1,m,k)]);
	}
}

数论

  • 中国剩余定理
  • 离散对数

bzoj4128 Matrix【2017.5.18】

#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define LL unsigned long long
const int maxn=75,r=131;
int n,p,m;
map<LL,int> mp;
int inc(int x,int y)
{
	x+=y;return x>=p?x-p:x;
}
int dec(int x,int y)
{
	x-=y;return x<0?x+p:x;
}
int inverse(int x)
{
	int ret=1;
	for (int k=p-2;k;k>>=1,x=x*x%p)
		if (k&1) ret=ret*x%p;
	return ret;
}
struct mat
{
	int a[maxn][maxn];
	LL h;
	void get()
	{
		h=0;
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				h=h*r+a[i][j];
	}
	void rd()
	{
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				scanf("%d",&a[i][j]);
		get();
	}
	void init()
	{
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				a[i][j]=(i==j);
		get();
	}
	mat operator * (const mat &m) const
	{
		mat ret;
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
			{
				ret.a[i][j]=0;
				for (int k=1;k<=n;k++)
					ret.a[i][j]=inc(ret.a[i][j],a[i][k]*m.a[k][j]%p);
			}
		ret.get();
		return ret;
	}
	mat inv()
	{
		mat ret;
		int x,t;
		ret.init();
		for (int i=1;i<=n;i++)
		{
			x=0;
			for (int j=i;j<=n;j++)
				if (a[j][i])
				{
					x=j;
					break;
				}
			if (x!=i)
				for (int j=1;j<=n;j++)
				{
					swap(a[i][j],a[x][j]);
					swap(ret.a[i][j],ret.a[x][j]);
				}
			t=inverse(a[i][i]);
			for (int j=1;j<=n;j++)
			{
				a[i][j]=a[i][j]*t%p;
				ret.a[i][j]=ret.a[i][j]*t%p;
			}
			for (int j=1;j<=n;j++)
				if (j!=i)
				{
					t=a[j][i];
					for (int k=1;k<=n;k++)
					{
						a[j][k]=dec(a[j][k],a[i][k]*t%p);
						ret.a[j][k]=dec(ret.a[j][k],ret.a[i][k]*t%p);
					}
				}
		}
		ret.get();
		return ret;
	}
}a,b,c;
int main()
{
	scanf("%d%d",&n,&p);
	a.rd();
	b.rd();
	m=sqrt(p);
	c.init();
	for (int i=0;i<m;i++)
	{
		if (!mp.count(c.h)) mp[c.h]=i;
		c=c*a;
		if (b.h==c.h)
		{
			printf("%d\n",i+1);
			return 0;
		}
	}
	c=c.inv();
	for (int i=1;;i++)
	{
		b=b*c;
		if (mp.count(b.h))
		{
			printf("%d\n",i*m+mp[b.h]);
			return 0;
		}
	}
}
  • 杜教筛

bzoj3944 Sum【2017.7.14】

#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=2000000,p=2333333;
int prm[maxn+5],fir[p+5],ne[p+5],val[p+5],tot,num;
LL phi[maxn+5],mu[maxn+5],ansphi[p+5],ansmu[p+5];
int find(int n,LL &resphi,LL &resmu)
{
	for (int i=fir[n%p];i;i=ne[i])
		if (val[i]==n)
		{
			resphi=ansphi[i];
			resmu=ansmu[i];
			return 1;
		}
	return 0;
}
void ins(int n,LL resphi,LL resmu)
{
	if (tot>p) return;
	int x=n%p;
	tot++;
	ne[tot]=fir[x];
	fir[x]=tot;
	val[tot]=n;
	ansphi[tot]=resphi;
	ansmu[tot]=resmu;
}
void solve(int n,LL &resphi,LL &resmu)
{
	if (n<=maxn)
	{
		resphi=phi[n];
		resmu=mu[n];
		return;
	}
	if (find(n,resphi,resmu)) return;
	LL tphi,tmu;
	resphi=n*(n+1LL)/2;
	resmu=1;
	for (unsigned int i=2,j;i<=n;i=j+1)
	{
		j=n/(n/i);
		solve(n/i,tphi,tmu);
		resphi-=(j-i+1)*tphi;
		resmu-=(j-i+1)*tmu;
	}
	ins(n,resphi,resmu);
}
int main()
{
	//freopen("a.in","r",stdin);
	int n;
	LL resphi,resmu;
	mu[1]=phi[1]=1;
	for (int i=2;i<=maxn;i++)
	{
		if (!phi[i])
		{
			prm[++num]=i;
			phi[i]=i-1;
			mu[i]=-1;
		}
		for (int j=1;j<=num&&(LL)i*prm[j]<=maxn;j++)
			if (i%prm[j])
			{
				mu[i*prm[j]]=-mu[i];
				phi[i*prm[j]]=phi[i]*(prm[j]-1);
			}
			else
			{
				mu[i*prm[j]]=0;
				phi[i*prm[j]]=phi[i]*prm[j];
				break;
			}
		phi[i]+=phi[i-1];
		mu[i]+=mu[i-1];
	}
	int T;
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d",&n);
		solve(n,resphi,resmu);
		printf("%lld %lld\n",resphi,resmu);
	}
}

bzoj4916神犇和蒟蒻【2017.7.15】

#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int p=1000000007,maxn=1000000,mod=2333333;
int inc(int x,int y)
{
	x+=y;
	return x>=p?x-p:x;
}
int dec(int x,int y)
{
	x-=y;
	return x<0?x+p:x;
}
int prm[maxn+10],phi[maxn+10],fir[mod+10],ne[mod+10],val[mod+10],ans[mod+10],tot,num;
int sum1(int n)
{
	return (LL)n*(n+1)/2%p;
}
int sum2(int n)
{
	int x=n,y=n+1,z=2*n+1;
	if (x%2==0) x/=2;
	else y/=2;
	if (x%3==0) x/=3;
	else if (y%3==0) y/=3;
	else z/=3;
	return (LL)x*y%p*z%p;
}
int find(int n,int &ret)
{
	for (int i=fir[n%mod];i;i=ne[i])
		if (val[i]==n)
		{
			ret=ans[i];
			return 1;
		}
	return 0;
}
void ins(int n,int ret)
{
	if (tot>mod) return;
	int x=n%mod;
	tot++;
	ne[tot]=fir[x];
	fir[x]=tot;
	val[tot]=n;
	ans[tot]=ret;
}
int solve(int n)
{
	if (n<=maxn) return phi[n];
	int ret;
	if (find(n,ret)) return ret;
	ret=sum2(n);
	for (int i=2,j;i<=n;i=j+1)
	{
		j=n/(n/i);
		ret=dec(ret,(LL)dec(sum1(j),sum1(i-1))*solve(n/i)%p);
	}
	ins(n,ret);
	return ret;
}
int main()
{
	phi[1]=1;
	for (int i=2;i<=maxn;i++)
	{
		if (!phi[i])
		{
			prm[++num]=i;
			phi[i]=i-1;
		}
		for (int j=1;j<=num&&(LL)i*prm[j]<=maxn;j++)
			if (i%prm[j]) phi[i*prm[j]]=phi[i]*(prm[j]-1);
			else
			{
				phi[i*prm[j]]=phi[i]*prm[j];
				break;
			}
		phi[i]=inc(phi[i-1],(LL)i*phi[i]%p);
	}
	int n;
	scanf("%d",&n);
	printf("1\n%d\n",solve(n));
}

高等数学

  • 矩阵求逆

bzoj4128 Matrix【2017.5.18】

#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define LL unsigned long long
const int maxn=75,r=131;
int n,p,m;
map<LL,int> mp;
int inc(int x,int y)
{
	x+=y;return x>=p?x-p:x;
}
int dec(int x,int y)
{
	x-=y;return x<0?x+p:x;
}
int inverse(int x)
{
	int ret=1;
	for (int k=p-2;k;k>>=1,x=x*x%p)
		if (k&1) ret=ret*x%p;
	return ret;
}
struct mat
{
	int a[maxn][maxn];
	LL h;
	void get()
	{
		h=0;
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				h=h*r+a[i][j];
	}
	void rd()
	{
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				scanf("%d",&a[i][j]);
		get();
	}
	void init()
	{
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				a[i][j]=(i==j);
		get();
	}
	mat operator * (const mat &m) const
	{
		mat ret;
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
			{
				ret.a[i][j]=0;
				for (int k=1;k<=n;k++)
					ret.a[i][j]=inc(ret.a[i][j],a[i][k]*m.a[k][j]%p);
			}
		ret.get();
		return ret;
	}
	mat inv()
	{
		mat ret;
		int x,t;
		ret.init();
		for (int i=1;i<=n;i++)
		{
			x=0;
			for (int j=i;j<=n;j++)
				if (a[j][i])
				{
					x=j;
					break;
				}
			if (x!=i)
				for (int j=1;j<=n;j++)
				{
					swap(a[i][j],a[x][j]);
					swap(ret.a[i][j],ret.a[x][j]);
				}
			t=inverse(a[i][i]);
			for (int j=1;j<=n;j++)
			{
				a[i][j]=a[i][j]*t%p;
				ret.a[i][j]=ret.a[i][j]*t%p;
			}
			for (int j=1;j<=n;j++)
				if (j!=i)
				{
					t=a[j][i];
					for (int k=1;k<=n;k++)
					{
						a[j][k]=dec(a[j][k],a[i][k]*t%p);
						ret.a[j][k]=dec(ret.a[j][k],ret.a[i][k]*t%p);
					}
				}
		}
		ret.get();
		return ret;
	}
}a,b,c;
int main()
{
	scanf("%d%d",&n,&p);
	a.rd();
	b.rd();
	m=sqrt(p);
	c.init();
	for (int i=0;i<m;i++)
	{
		if (!mp.count(c.h)) mp[c.h]=i;
		c=c*a;
		if (b.h==c.h)
		{
			printf("%d\n",i+1);
			return 0;
		}
	}
	c=c.inv();
	for (int i=1;;i++)
	{
		b=b*c;
		if (mp.count(b.h))
		{
			printf("%d\n",i*m+mp[b.h]);
			return 0;
		}
	}
}
  • O ( k 2 log ⁡ n ) O(k^2\log n) O(k2logn)递推

bzoj4161 Shlw loves matrixI【2017.5.18】

#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxk=4010,p=1000000007;
int n,k,f[maxk],h[maxk];
int inc(int x,int y)
{
	x+=y;return x>=p?x-p:x;
}
int dec(int x,int y)
{
	x-=y;return x<0?x+p:x;
}
struct mat
{
	int a[maxk];
	mat operator * (const mat &m) const
	{
		mat ret;
		for (int i=0;i<=2*k-2;i++) ret.a[i]=0;
		for (int i=0;i<k;i++)
			for (int j=0;j<k;j++)
				ret.a[i+j]=inc(ret.a[i+j],(LL)a[i]*m.a[j]%p);
		for (int i=2*k-2;i>=k;i--)
			for (int j=1;j<=k;j++)
				ret.a[i-j]=inc(ret.a[i-j],(LL)ret.a[i]*f[j]%p);
		return ret;
	}
}a,b;
int main()
{
	int ans=0;
	scanf("%d%d",&n,&k);
	for (int i=1;i<=k;i++)
	{
		scanf("%d",&f[i]);
		f[i]=dec(f[i],0);
	}
	for (int i=0;i<k;i++)
	{
		scanf("%d",&h[i]);
		h[i]=dec(h[i],0);
	}
	a.a[1]=1;
	b.a[0]=1;
	for (int i=n-k+1;i;i>>=1,a=a*a)
		if (i&1) b=b*a;
	for (int i=k;i<=2*k-2;i++)
		for (int j=1;j<=k;j++)
			h[i]=inc(h[i],(LL)h[i-j]*f[j]%p);
	for (int i=0;i<k;i++)
		ans=inc(ans,(LL)b.a[i]*h[k+i-1]%p);
	printf("%d\n",ans);
}

【2017.7.15】

#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int p=1000000007,maxk=4010;
int inc(int x,int y)
{
	x+=y;
	return x>=p?x-p:x;
}
int f[maxk],h[maxk],k,n;
struct mat
{
	int a[maxk];
	mat operator * (const mat &m) const
	{
		mat ret;
		for (int i=0;i<=2*k-2;i++)
			ret.a[i]=0;
		for (int i=0;i<k;i++)
			for (int j=0;j<k;j++)
				ret.a[i+j]=inc(ret.a[i+j],(LL)a[i]*m.a[j]%p);
		for (int i=2*k-2;i>=k;i--)
		{
			for (int j=1;j<=k;j++) ret.a[i-j]=inc(ret.a[i-j],(LL)ret.a[i]*f[j]%p);
			ret.a[i]=0;
		}
		return ret;
	}
}base,res;
int main()
{
	//freopen("d.in","r",stdin);
	int ans=0;
	scanf("%d%d",&n,&k);
	for (int i=1;i<=k;i++)
	{
		scanf("%d",&f[i]);
		if (f[i]<0) f[i]+=p;
	}
	for (int i=0;i<k;i++)
	{
		scanf("%d",&h[i]);
		if (h[i]<0) h[i]+=p;
	}
	base.a[1]=1;
	res.a[0]=1;
	for (n-=k-1;n;n>>=1,base=base*base)
		if (n&1) res=res*base;
	for (int i=k;i<=2*k-2;i++)
		for (int j=1;j<=k;j++)
			h[i]=inc(h[i],(LL)f[j]*h[i-j]%p);
	for (int i=0;i<k;i++) ans=inc(ans,(LL)res.a[i]*h[k+i-1]%p);
	printf("%d\n",ans);
}
  • 矩阵树定理

【HEOI2015】bzoi4031 小Z的房间【2017.5.18】

#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=110,maxl=15,p=1000000000;
char map[maxl][maxl];
int id[maxl][maxl],a[maxn][maxn],r,c,n;
int main()
{
	int flag=0,x,y,t,ans=1;
	scanf("%d%d",&r,&c);
	for (int i=1;i<=r;i++)
	{
		scanf("%s",map[i]+1);
		for (int j=1;j<=c;j++)
			if (map[i][j]=='.')
				id[i][j]=++n;
	}
	for (int i=1;i<=r;i++)
		for (int j=1;j<=c;j++)
			if (map[i][j]=='.')
			{
				x=id[i][j];
				if (i<r&&map[i+1][j]=='.')
				{
					y=id[i+1][j];
					a[x][y]--;
					a[y][x]--;
					a[x][x]++;
					a[y][y]++;
				}
				if (j<c&&map[i][j+1]=='.')
				{
					y=id[i][j+1];
					a[x][y]--;
					a[y][x]--;
					a[x][x]++;
					a[y][y]++;
				}
			}
	for (int i=1;i<n;i++)
		for (int j=1;j<n;j++)
			if (a[i][j]<0) a[i][j]+=p;
	for (int i=1;i<n;i++)
	{
		x=0;
		for (int j=i;j<n;j++)
			if (a[j][i])
			{
				x=j;
				break;
			}
		if (!x) continue;
		if (x!=i)
		{
			flag^=1;
			for (int j=1;j<n;j++) swap(a[i][j],a[x][j]);
		}
		for (int j=i+1;j<n;j++)
			while (a[j][i])
			{
				if (a[j][i]<a[i][i])
				{
					flag^=1;
					for (int k=1;k<n;k++) swap(a[j][k],a[i][k]);
				}
				t=a[j][i]/a[i][i];
				for (int k=1;k<n;k++)
					a[j][k]=(a[j][k]-(LL)a[i][k]*t%p+p)%p;
			}
	}
	for (int i=1;i<n;i++) ans=(LL)ans*a[i][i]%p;
	if (flag) ans=(p-ans)%p;
	printf("%d\n",ans);
}
  • FFT
    bzoj2179 FFT快速傅立叶(FFT)【2017.4.19】
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double pi=acos(-1);
struct Complex
{
	double x,y;
	Complex operator + (const Complex &c) const
	{
		return (Complex){x+c.x,y+c.y};
	}
	Complex operator - (const Complex &c) const
	{
		return (Complex){x-c.x,y-c.y};
	}
	Complex operator * (const Complex &c) const
	{
		return (Complex){x*c.x-y*c.y,x*c.y+y*c.x};
	}
}a[200010],b[200010],w[200010],t1,t2;
char s[200010];
int rev[200010],ans[200010],l,m;
void fft(Complex *a,int fl)
{
	int x;
	for (int i=0;i<l;i++)
		if (rev[i]>i) swap(a[i],a[rev[i]]);
	for (int i=1;i<=m;i++)
		for (int j=0;j<l;j+=1<<i)
		{
			x=0;
			for (int k=j;k<(j+(1<<i-1));k++)
			{
				t1=a[k];
				t2=a[k+(1<<i-1)];
				a[k]=t1+t2*w[x];
				a[k+(1<<i-1)]=t1-t2*w[x];
				x+=fl*(1<<m-i);
				if (x<0) x+=l;
			}
		}
}
int main()
{
	int n,nn;
	scanf("%d",&n);
	scanf("%s",s);
	for (int i=0;i<n;i++) a[i].x=s[n-i-1]-'0';
	scanf("%s",s);
	for (int i=0;i<n;i++) b[i].x=s[n-i-1]-'0';
	while ((1<<m)<n*2) m++;
	l=1<<m;
	w[0]=(Complex){1,0};
	w[1]=(Complex){cos(2*pi/l),sin(2*pi/l)};
	for (int i=2;i<l;i++)
	{
		w[i]=w[i/2]*w[i/2];
		if (i&1) w[i]=w[i]*w[1];
	}
	for (int i=0;i<l;i++)
		for (int j=0;j<m;j++)
			rev[i]|=((i>>j)&1)<<m-j-1;
	fft(a,1);
	fft(b,1);
	for (int i=0;i<l;i++) a[i]=a[i]*b[i];
	fft(a,-1);
	for (int i=0;i<l;i++) ans[i]=int(a[i].x/l+0.5);
	for (int i=0;i<2*n-2;i++)
	{
		ans[i+1]+=ans[i]/10;
		ans[i]%=10;
	}
	nn=2*n-1;
	while (!ans[nn-1]) nn--;
	for (int i=nn-1;i>=0;i--) printf("%d",ans[i]);
}

【ZJOI2014】bzoj3527 力【2017.5.18】

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=800010;
const double pi=acos(-1);
struct Complex
{
	double a,b;
	Complex operator + (const Complex &c) const
	{
		return (Complex){a+c.a,b+c.b};
	}
	Complex operator - (const Complex &c) const
	{
		return (Complex){a-c.a,b-c.b};
	}
	Complex operator * (const Complex &c) const
	{
		return (Complex){a*c.a-b*c.b,a*c.b+b*c.a};
	}
}w[maxn],a[maxn],b[maxn],t1,t2;
int rev[maxn],n,l,t;
void fft(Complex *a,int flag)
{
	int x;
	for (int i=0;i<l;i++)
		if (rev[i]>i) swap(a[i],a[rev[i]]);
	for (int i=1;i<=t;i++)
		for (int j=0;j<l;j+=1<<i)
		{
			x=0;
			for (int k=j;k<j+(1<<i-1);k++)
			{
				t1=a[k];
				t2=a[k+(1<<i-1)];
				a[k]=t1+t2*w[x];
				a[k+(1<<i-1)]=t1-t2*w[x];
				x+=flag*(1<<t-i);
				if (x<0) x+=l;
			}
		}
}
int main()
{
	scanf("%d",&n);
	for (int i=0;i<n;i++) scanf("%lf",&a[i].a);
	for (int i=0;i<n-1;i++) b[i].a=-1/((double)(n-i-1)*(n-i-1));
	for (int i=n;i<2*n-1;i++) b[i].a=1/((double)(i-n+1)*(i-n+1));
	l=1,t=0;
	while (l<4*n-3) l<<=1,t++;
	for (int i=0;i<l;i++) w[i]=(Complex){cos(2*pi*i/l),sin(2*pi*i/l)};
	for (int i=0;i<l;i++)
		for (int j=0;j<t;j++) rev[i]|=((i>>j)&1)<<(t-j-1);
	fft(a,1);
	fft(b,1);
	for (int i=0;i<l;i++) a[i]=a[i]*b[i];
	fft(a,-1);
	for (int i=n-1;i<2*n-1;i++) printf("%.3f\n",a[i].a/l);
}
  • 辛普森自适应积分

计算几何

  • 射线法
  • 凸包
  • 旋转卡壳
  • 半平面交

图论

  • 树链剖分
  • LCT
    【HNOI2010】bzoj2002 弹飞绵羊
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=400010;
int rd()
{
	int x=0;
	char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x;
}
int fa[maxn],son[maxn][2],siz[maxn],a[maxn],inv[maxn],sta[maxn],n;
void down(int x)
{
	if (inv[x])
	{
		inv[x]=0;
		swap(son[x][0],son[x][1]);
		if (son[x][0]) inv[son[x][0]]^=1;
		if (son[x][1]) inv[son[x][1]]^=1;
	}
}
void up(int x)
{
	down(x);
	siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
}
int isroot(int x)
{
	return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
void rot(int u,int f)
{
	int v=son[u][f],x=son[v][f^1],y=fa[u];
	if (son[y][0]==u) son[y][0]=v;
	if (son[y][1]==u) son[y][1]=v;
	fa[v]=y;
	son[v][f^1]=u;
	fa[u]=v;
	son[u][f]=x;
	if (x) fa[x]=u;
	up(u);
	up(v);
}
void splay(int u)
{
	int top=0,x,y,fx,fy;
	for (int i=u;;i=fa[i])
	{
		sta[++top]=i;
		if (isroot(i)) break;
	}
	for (;top;top--) down(sta[top]);
	while (!isroot(u))
	{
		x=fa[u];
		fx=son[x][1]==u;
		if (isroot(x)) rot(x,fx);
		else
		{
			y=fa[x];
			fy=son[y][1]==x;
			if (fx==fy) rot(y,fy),rot(x,fx);
			else rot(x,fx),rot(y,fy);
		}
	}
}
void access(int u)
{
	int v=0;
	while (u)
	{
		splay(u);
		son[u][1]=v;
		up(u);
		v=u;
		u=fa[u];
	}
}
void makeroot(int x)
{
	access(x);
	splay(x);
	inv[x]^=1;
	up(x);
}
void link(int x,int y)
{
	makeroot(y);
	fa[x]=y;
}
void cut(int x,int y)
{
	makeroot(y);
	access(x);
	splay(x);
	son[x][0]=fa[y]=0;
	up(x);
}
int qry(int x)
{
	makeroot(n+1);
	access(x);
	splay(x);
	return siz[x]-1;
}
int main()
{
	int q,opt,x,y;
	n=rd();
	for (int i=1;i<=n;i++) siz[i]=1;
	for (int i=1;i<=n;i++)
	{
		a[i]=rd();
		if (i+a[i]>n) a[i]=n-i+1;
		link(i,i+a[i]);
	}
	q=rd();
	while (q--)
	{
		opt=rd();
		if (opt==1) printf("%d\n",qry(rd()+1));
		else
		{
			x=rd()+1;
			y=rd();
			cut(x,x+a[x]);
			a[x]=y;
			if (x+a[x]>n) a[x]=n-x+1;
			link(x,x+a[x]);
		}
	}
}

bzoj2631 tree【2017.5.16】

#include<cstdio>
#include<algorithm>
using namespace std;
#define UI unsigned int
const int maxn=200010,p=51061;
int rd()
{
	int x=0;
	char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x;
}
char rdc()
{
	char c=getchar();
	while (c!='+'&&c!='*'&&c!='/'&&c!='-') c=getchar();
	return c;
}
int inc(int x,int y)
{
	x+=y;return x>=p?x-p:x;
}
int son[maxn][2],fa[maxn],tagp[maxn],tagm[maxn],sum[maxn],val[maxn],siz[maxn],inv[maxn],
sta[maxn],
n;
int is(int u)
{
	return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;
}
void down(int u)
{
	int v;
	if (inv[u])
	{
		inv[u]=0;
		swap(son[u][0],son[u][1]);
		if (v=son[u][0]) inv[v]^=1;
		if (v=son[u][1]) inv[v]^=1; 
	}
	if (tagm[u]!=1)
	{
		val[u]=(UI)val[u]*tagm[u]%p;
		sum[u]=(UI)sum[u]*tagm[u]%p;
		if (v=son[u][0])
		{
			tagm[v]=(UI)tagm[v]*tagm[u]%p;
			tagp[v]=(UI)tagp[v]*tagm[u]%p;
		}
		if (v=son[u][1])
		{
			tagm[v]=(UI)tagm[v]*tagm[u]%p;
			tagp[v]=(UI)tagp[v]*tagm[u]%p;
		}
		tagm[u]=1;
	}
	if (tagp[u])
	{
		val[u]=inc(val[u],tagp[u]);
		sum[u]=inc(sum[u],(UI)tagp[u]*siz[u]%p);
		if (v=son[u][0]) tagp[v]=inc(tagp[v],tagp[u]);
		if (v=son[u][1]) tagp[v]=inc(tagp[v],tagp[u]);
		tagp[u]=0;
	}
}
void up(int u)
{
	down(u);
	if (son[u][0]) down(son[u][0]);
	if (son[u][1]) down(son[u][1]);
	int v;
	sum[u]=val[u];
	siz[u]=1;
	if (v=son[u][0])
	{
		sum[u]=inc(sum[u],sum[v]);
		siz[u]=siz[u]+siz[v];
	}
	if (v=son[u][1])
	{
		sum[u]=inc(sum[u],sum[v]);
		siz[u]=siz[u]+siz[v];
	}
}
void rot(int u,int f)
{
	int v=son[u][f],x=son[v][f^1],y=fa[u];
	if (!is(u)) son[y][son[y][1]==u]=v;
	fa[v]=y;
	son[v][f^1]=u;
	fa[u]=v;
	son[u][f]=x;
	if (x) fa[x]=u;
	up(u);
	up(v);
}
void splay(int u)
{
	int v,x,y,xx,yy,t=u,top=0;
	while (1)
	{
		sta[++top]=t;
		if (is(t)) break;
		t=fa[t];
	}
	for (;top;top--) down(sta[top]);
	while (!is(u))
	{
		x=fa[u];
		xx=son[x][1]==u;
		if (is(x)) rot(x,xx);
		else
		{
			y=fa[x];
			yy=son[y][1]==x;
			if (xx==yy) rot(y,yy),rot(x,xx);
			else rot(x,xx),rot(y,yy);
		}
	}
}
void access(int u)
{
	int v=0,t=u;
	while (u)
	{
		splay(u);
		son[u][1]=v;
		up(u);
		v=u;
		u=fa[u];
	}
	splay(t);
}
void make(int u)
{
	access(u);
	inv[u]^=1;
	up(u);
}
void link(int u,int v)
{
	make(u);
	fa[u]=v;
}
void cut(int u,int v)
{
	make(u);
	access(v);
	son[v][0]=fa[u]=0;
	up(v);
}
int query(int u,int v)
{
	make(u);
	access(v);
	return sum[v];
}
void modip(int u,int v,int x)
{
	make(u);
	access(v);
	tagp[v]=inc(tagp[v],x);
}
void modim(int u,int v,int x)
{
	make(u);
	access(v);
	tagp[v]=(UI)tagp[v]*x%p;
	tagm[v]=(UI)tagm[v]*x%p;
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	char c;
	int u,v,x,y,q;
	n=rd();
	q=rd();
	for (int i=1;i<=n;i++) sum[i]=val[i]=tagm[i]=siz[i]=1;
	for (int i=1;i<n;i++)
	{
		u=rd();
		v=rd();
		link(u,v);
	}
	while (q--)
	{
		c=rdc();
		u=rd();
		v=rd();
		if (c=='/') printf("%d\n",query(u,v));
		else
		{
			x=rd();
			if (c=='+') modip(u,v,x);
			else if (c=='*') modim(u,v,x);
			else
			{
				y=rd();
				cut(u,v);
				link(x,y);
			}
		}
	}
}
  • 点分治
    poj1741 Tree【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=10010;
struct node
{
	int bel,dis;
	bool operator < (const node &n) const
	{
		return dis<n.dis;
	}
}a[maxn];
int fir[maxn],vis[maxn],ne[2*maxn],to[2*maxn],w[2*maxn],size[maxn],val[maxn],sum[maxn],
rt,n,m,ans,S,tot;
void add(int num,int u,int v,int x)
{
	ne[num]=fir[u];
	fir[u]=num;
	to[num]=v;
	w[num]=x;
}
void dfs1(int u,int fa)
{
	size[u]=1;
	val[u]=0;
	for (int i=fir[u];i;i=ne[i])
		if (to[i]!=fa&&!vis[to[i]])
		{
			dfs1(to[i],u);
			size[u]+=size[to[i]];
			val[u]=max(val[u],size[to[i]]);
		}
	val[u]=max(val[u],S-size[u]);
	if (rt==-1||val[u]<val[rt]) rt=u;
}
void dfs2(int u,int fa,int b,int d)
{
	size[u]=1;
	a[++tot]=(node){b,d};
	for (int i=fir[u];i;i=ne[i])
		if (to[i]!=fa&&!vis[to[i]])
		{
			dfs2(to[i],u,b,d+w[i]);
			size[u]+=size[to[i]];
		}
}
void solve(int u)
{
	int r,num=0,s=0;
	rt=-1;
	dfs1(u,-1);
	r=rt;
	a[tot=1]=(node){0,0};
	for (int i=fir[r];i;i=ne[i])
		if (!vis[to[i]])
			dfs2(to[i],r,++num,w[i]);
	sort(a+1,a+tot+1);
	for (int i=0;i<=num;i++) sum[i]=0;
	for (int i=tot,j=0;i;i--)
	{
		while (j<tot&&a[j+1].dis+a[i].dis<=m) sum[a[++j].bel]++;
		ans+=j-sum[a[i].bel];
	}
	vis[r]=1;
	for (int i=fir[r];i;i=ne[i])
		if (!vis[to[i]])
		{
			S=size[to[i]];
			solve(to[i]);
		}
}
void solve()
{
	int u,v,x;
	for (int i=1;i<=n;i++) fir[i]=vis[i]=0;
	ans=0;
	for (int i=1;i<n;i++)
	{
		scanf("%d%d%d",&u,&v,&x);
		add(i*2,u,v,x);
		add(i*2+1,v,u,x);
	}
	S=n;
	solve(1);
	printf("%d\n",ans/2);
}
int main()
{
	while (scanf("%d%d",&n,&m)&&n) solve();
}
  • 边分治
  • 动态点分治

【ZJOI2007】bzoj1095 捉迷藏【2017.5.18】

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100010;
struct heap
{
    priority_queue<int> a,b;
    void ins(int x)
    {
        a.push(x);
    }
    void del(int x)
    {
        b.push(x);
    }
    int size()
    {
        return a.size()-b.size();
    }
    int top()
    {
        while (!b.empty()&&a.top()==b.top())
        {
            a.pop();
            b.pop();
        }
        return a.top();
    }
    int get()
    {
        int x=top();
        del(x);
        int y=top();
        ins(x);
        return x+y;
    }
}q1[maxn],q2[maxn],q3;
int fir[maxn],ne[2*maxn],to[2*maxn],
vis[maxn],size[maxn],val[maxn],fa[maxn],flag[maxn],
mn[2*maxn][20],pos[maxn],dep[maxn],log[2*maxn],
n,rt,clo;
void add(int num,int u,int v)
{
    ne[num]=fir[u];
    fir[u]=num;
    to[num]=v;
}
void dfs0(int u,int fa,int d)
{
    dep[u]=d;
    mn[pos[u]=++clo][0]=d;
    for (int i=fir[u];i;i=ne[i])
        if (to[i]!=fa)
        {
            dfs0(to[i],u,d+1);
            mn[++clo][0]=d;
        }
}
void dfs1(int u,int fa)
{
    size[u]=1;
    for (int i=fir[u];i;i=ne[i])
        if (!vis[to[i]]&&to[i]!=fa)
        {
            dfs1(to[i],u);
            size[u]+=size[to[i]];
        }
}
int dfs2(int u,int fa,int S)
{
    int ret=-1,x;
    val[u]=S-size[u];
    for (int i=fir[u];i;i=ne[i])
        if (!vis[to[i]]&&to[i]!=fa)
        {
            x=dfs2(to[i],u,S);
            val[u]=max(val[u],size[to[i]]);
            if (ret==-1||val[x]<val[ret]) ret=x;
        }
    if (ret==-1||val[u]<val[ret]) ret=u;
    return ret;
}
void dfs3(int u,int fa,int bel,int dis)
{
    q1[bel].ins(dis);
    for (int i=fir[u];i;i=ne[i])
        if (!vis[to[i]]&&to[i]!=fa)
            dfs3(to[i],u,bel,dis+1);
}
int solve(int u)
{
    dfs1(u,-1);
    int r=dfs2(u,-1,size[u]),x;
    vis[r]=1;
    for (int i=fir[r];i;i=ne[i])
        if (!vis[to[i]])
        {
            x=solve(to[i]);
            dfs3(to[i],r,x,1);
            fa[x]=r;
            q2[r].ins(q1[x].top());
        }
    q2[r].ins(0);
    vis[r]=0;
    if (q2[r].size()>=2) q3.ins(q2[r].get());
    return r;
}
int dis(int u,int v)
{
    int x=pos[u],y=pos[v],k;
    if (x>y) swap(x,y);
    k=log[y-x+1];
    return dep[u]+dep[v]-2*min(mn[x][k],mn[y-(1<<k)+1][k]);
}
void ins(int u)
{
    if (q2[u].size()>=2) q3.del(q2[u].get());
    q2[u].ins(0);
    if (q2[u].size()>=2) q3.ins(q2[u].get());
    for (int i=u;fa[i];i=fa[i])
    {
        if (q2[fa[i]].size()>=2) q3.del(q2[fa[i]].get());
        if (q1[i].size()) q2[fa[i]].del(q1[i].top());
        q1[i].ins(dis(u,fa[i]));
        if (q1[i].size()) q2[fa[i]].ins(q1[i].top());
        if (q2[fa[i]].size()>=2) q3.ins(q2[fa[i]].get());
    }
}
void del(int u)
{
    if (q2[u].size()>=2) q3.del(q2[u].get());
    q2[u].del(0);
    if (q2[u].size()>=2) q3.ins(q2[u].get());
    for (int i=u;fa[i];i=fa[i])
    {
        if (q2[fa[i]].size()>=2) q3.del(q2[fa[i]].get());
        if (q1[i].size()) q2[fa[i]].del(q1[i].top());
        q1[i].del(dis(u,fa[i]));
        //printf("%d\n",q1[i].size());
        if (q1[i].size()) q2[fa[i]].ins(q1[i].top());
        if (q2[fa[i]].size()>=2) q3.ins(q2[fa[i]].get());
    }
}
int main()
{
    int u,v,q,now;
    char c[3];
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        add(i*2,u,v);
        add(i*2+1,v,u);
    }
    dfs0(1,-1,1);
    for (int i=1;(1<<i)<=clo;i++) log[1<<i]=i;
    for (int i=3;i<=clo;i++)
        if (!log[i]) log[i]=log[i-1];
    for (int k=1;k<=log[clo];k++)
        for (int i=1;i+(1<<k)-1<=clo;i++)
            mn[i][k]=min(mn[i][k-1],mn[i+(1<<k-1)][k-1]);
    rt=solve(1);
    now=n;
    scanf("%d",&q);
    while (q--)
    {
        scanf("%s",c);
        if (c[0]=='C')
        {
            scanf("%d",&u);
            if (flag[u]) ins(u),now++;
            else del(u),now--;
            flag[u]^=1;
        }
        else
        {
            if (now==0) printf("-1\n");
            else if (now==1) printf("0\n");
            else printf("%d\n",q3.top());
        }
    }
}
  • 2-SAT

poj3678 Katu Puzzle【2017.5.19】

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2010,maxm=2000010;
int fir[maxn],ne[maxm],to[maxm],dfn[maxn],low[maxn],sta[maxn],bel[maxn],in[maxn],
n,m,num,clo,tot,top;
void add(int u,int v)
{
	num++;
	ne[num]=fir[u];
	fir[u]=num;
	to[num]=v;
}
void dfs(int u)
{
	int x;
	dfn[u]=low[u]=++clo;
	sta[++top]=u;
	in[u]=1;
	for (int i=fir[u];i;i=ne[i])
		if (!dfn[to[i]])
		{
			dfs(to[i]);
			low[u]=min(low[u],low[to[i]]);
		}
		else if (in[to[i]]) low[u]=min(low[u],dfn[to[i]]);
	if (low[u]==dfn[u])
	{
		tot++;
		do
		{
			x=sta[top--];
			bel[x]=tot;
			in[x]=0;
		}
		while (x!=u);
	}
}
int main()
{
	int u,v,x;
	char s[10];
	scanf("%d%d",&n,&m);
	while (m--)
	{
		scanf("%d%d%d%s",&u,&v,&x,s);
		switch (s[0])
		{
			case 'A':
				if (x==0)
				{
					add(v*2+1,u*2);
					add(u*2+1,v*2);
				}
				else
				{
					add(u*2,u*2+1);
					add(v*2,v*2+1);
				}
				break;
			case 'O':
				if (x==0)
				{
					add(u*2+1,u*2);
					add(v*2+1,v*2);
				}
				else
				{
					add(u*2,v*2+1);
					add(v*2,u*2+1);
				}
				break;
			case 'X':
				if (x==0)
				{
					add(u*2,v*2);
					add(v*2,u*2);
					add(u*2+1,v*2+1);
					add(v*2+1,u*2+1);
				}
				else
				{
					add(u*2,v*2+1);
					add(v*2,u*2+1);
					add(u*2+1,v*2);
					add(v*2+1,u*2);
				}
				break;
		}
	}
	for (int i=0;i<n*2;i++)
		if (!dfn[i]) dfs(i);
	for (int i=0;i<n;i++)
		if (bel[i*2]==bel[i*2+1])
		{
			printf("NO\n");
			return 0;
		}
	printf("YES\n");
}

动态规划

  • 斜率优化dp
    【APIO2010】bzoj1911 特别行动队
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=1000010;
int rd()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9')
	{
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
LL dp[maxn],s[maxn],h[maxn],g[maxn],a,b,c;
int que[maxn],n;
double get(int i,int j)
{
	return (double)(h[j]-h[i])/(s[j]-s[i]);
}
int main()
{
	int hd=1,tl=1;
	n=rd();
	a=rd();
	b=rd();
	c=rd();
	for (int i=1;i<=n;i++) s[i]=s[i-1]+rd();
	for (int i=1;i<=n;i++)
	{
		while (hd<tl&&get(que[hd],que[hd+1])<=-2*a*s[i]) hd++;
		dp[i]=dp[que[hd]]+a*(s[i]-s[que[hd]])*(s[i]-s[que[hd]])+b*(s[i]-s[que[hd]])+c;
		h[i]=-a*s[i]*s[i]+b*s[i]-dp[i];
		while (hd<tl&&get(que[tl-1],que[tl])>=get(que[tl],i)) tl--;
		que[++tl]=i;
	}
	printf("%lld\n",dp[n]);
}
  • 插头dp

【SCOI2011】bzoj2331 地板【2017.5.19】

#include<cstdio>
#include<algorithm>
using namespace std;
const int p=20110520;
char mp[110][110];
int dp[2][4200010],last[4200010],f[2][4200010],
r,c,clo,tot,y;
int inc(int x,int y)
{
    x+=y;return x>=p?x-p:x;
}
void upd(int x)
{
    if (last[x]==clo+1) dp[clo&1^1][x]=inc(dp[clo&1^1][x],y);
    else
    {
        last[x]=clo+1;
        f[clo&1^1][++tot]=x;
        dp[clo&1^1][x]=y;
    }
}
int main()
{
    int x,t1,ans=0;
    scanf("%d%d",&r,&c);
    for (int i=1;i<=r;i++) scanf("%s",mp[i]+1);
    if (r<c)
    {
        for (int i=1;i<=c;i++)
            for (int j=i+1;j<=c;j++)
                swap(mp[i][j],mp[j][i]);
        swap(r,c);
    }
    f[1][tot=1]=0;
    dp[1][0]=1;
    for (int i=1;i<=r;i++)
        for (int j=1;j<=c;j++)
        {
            clo++;
            t1=tot;
            tot=0;
            for (int k=1;k<=t1;k++)
            {
                x=f[clo&1][k];
                y=dp[clo&1][x];
                if (mp[i][j]=='*')
                {
                    if (!(x&1)&&!((x>>2)&1)) upd(x>>2);
                    continue;
                }
                if (!(x&1))
                {
                    if (!(x&4))
                    {
                        upd((x>>2)|(1<<2*c));
                        if (j<c)
                        {
                            upd((x>>2)|1);
                            upd((x>>2)|3|(3<<2*c));
                        }
                    }
                    else if (!(x&8))
                    {
                        upd(((x>>2)^1)|(1<<2*c));
                        if (j<c) upd((x>>2)|3);
                    }
                    else
                    {
                        upd((x>>2)^3);
                        upd(((x>>2)^3)|(3<<2*c));
                    }
                }
                else if (!(x&2))
                {
                    if (!(x&4))
                    {
                        if (j<c) upd((x>>2)|1);
                        upd((x>>2)|(3<<2*c));
                    }
                    else if (!(x&8)) upd((x>>2)^1);
                }
                else
                {
                    if (!(x&4))
                    {
                        upd(x>>2);
                        if (j<c) upd((x>>2)|3);
                    }
                }
            }
        }
    printf("%d\n",last[0]==clo+1?dp[clo&1^1][0]:0);
}
  • 数位dp
  • 四边形不等式

其他算法

  • CDQ分治
    bzoj3262 陌上花开【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010,maxm=200010;
int rd()
{
	int x=0;
	char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x;
}
struct flower
{
	int a,b,c,res,num;
	bool operator < (const flower &f) const
	{
		if (a!=f.a) return a<f.a;
		if (b!=f.b) return b<f.b;
		return c<f.c;
	}
}a[maxn],b[maxn];
int s[maxm],ans[maxn],n,m;
void add(int k,int x)
{
	for (;k<=m;k+=k&-k) s[k]+=x;
}
int qry(int k)
{
	int ret=0;
	for (;k;k-=k&-k) ret+=s[k];
	return ret;
}
void solve(int l,int r)
{
	if (l==r) return;
	int mid=(l+r)/2;
	solve(l,mid);
	solve(mid+1,r);
	for (int i=l;i<=r;i++) b[i]=a[i];
	for (int i=l,j=mid+1,now=l;i<=mid||j<=r;)
		if (j>r||(i<=mid&&b[i].b<=b[j].b))
		{
			add(b[i].c,b[i].num);
			a[now++]=b[i++];
		}
		else
		{
			b[j].res+=qry(b[j].c);
			a[now++]=b[j++];
		}
	for (int i=l;i<=mid;i++) add(b[i].c,-b[i].num);
}
int main()
{
	int N=1;
	n=rd();
	m=rd();
	for (int i=1;i<=n;i++)
	{
		a[i].a=rd();
		a[i].b=rd();
		a[i].c=rd();
		a[i].num=1;
	}
	sort(a+1,a+n+1);
	b[1]=a[1];
	for (int i=2;i<=n;i++)
		if (a[i-1]<a[i]) b[++N]=a[i];
		else b[N].num++;
	for (int i=1;i<=N;i++) a[i]=b[i];
	solve(1,N);
	for (int i=1;i<=N;i++) ans[a[i].res+a[i].num-1]+=a[i].num;
	for (int i=0;i<n;i++) printf("%d\n",ans[i]);
}
  • 整体二分

bzoj2738 矩阵乘法【2017.5.16】

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=510,maxq=60010;
int rd()
{
	int x=0;
	char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x;
}
struct qry
{
	int x1,y1,x2,y2,id,res,k;
}f[maxq],g[maxq];
struct node
{
	int x,y,v;
	bool operator < (const node &n) const
	{
		return v<n.v;
	}
}a[maxn*maxn];
int s[maxn][maxn],ans[maxq],n,q,tot;
void add(node a)
{
	for (int i=a.x;i<=n;i+=i&-i)
		for (int j=a.y;j<=n;j+=j&-j)
			s[i][j]++;
}
void dec(node a)
{
	for (int i=a.x;i<=n;i+=i&-i)
		for (int j=a.y;j<=n;j+=j&-j)
			s[i][j]--;
}
int query(qry a)
{
	int ret=0;
	for (int i=a.x2;i;i-=i&-i)
		for (int j=a.y2;j;j-=j&-j)
			ret+=s[i][j];
	for (int i=a.x1-1;i;i-=i&-i)
		for (int j=a.y2;j;j-=j&-j)
			ret-=s[i][j];
	for (int i=a.x2;i;i-=i&-i)
		for (int j=a.y1-1;j;j-=j&-j)
			ret-=s[i][j];
	for (int i=a.x1-1;i;i-=i&-i)
		for (int j=a.y1-1;j;j-=j&-j)
			ret+=s[i][j];
	return ret;
}
void solve(int l,int r,int L,int R)
{
	if (L==R)
	{
		for (int i=l;i<=r;i++) f[i].res=a[L].v;
		return;
	}
	int mid=(L+R)/2,m=r,x;
	for (int i=L;i<=mid;i++) add(a[i]);
	for (int i=l,j=l,k=r;i<=r;i++)
	{
		x=query(f[i]);
		if (f[i].k<=x) g[j++]=f[i];
		else
		{
			f[i].k-=x;
			g[k--]=f[i];
			m=k;
		}
	}
	for (int i=L;i<=mid;i++) dec(a[i]);
	for (int i=l;i<=r;i++) f[i]=g[i];
	solve(l,m,L,mid);
	solve(m+1,r,mid+1,R);
}
int main()
{
	int x1,y1,x2,y2,k;
	n=rd();
	q=rd();
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
			a[++tot]=(node){i,j,rd()};
	for (int i=1;i<=q;i++)
	{
		x1=rd();
		y1=rd();
		x2=rd();
		y2=rd();
		k=rd();
		f[i]=(qry){x1,y1,x2,y2,i,0,k};
	}
	sort(a+1,a+tot+1);
	solve(1,q,1,tot);
	for (int i=1;i<=q;i++) ans[f[i].id]=f[i].res;
	for (int i=1;i<=q;i++) printf("%d\n",ans[i]);
}

【ZJOI2013】bzoj3110 K大数查询【2017.7.14】

#include<cstdio>
#include<algorithm>
using namespace std;
#define UI unsigned int
const int maxn=50010,maxt=2000000;
int rdi()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9')
	{
		if (c=='-') f=-1;
		c=getchar();
	}
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
UI rdu()
{
	UI x=0;
	char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x;
}
struct str
{
	int l,r,id,f;
	UI x;
}a[maxn],b[maxn],c[maxn];
UI sum[maxt];
int n,m,o,val[maxn],ord[maxn],ans[maxn],tag[maxt];
void down(int u,int L,int R)
{
	if (L<R)
	{
		tag[u*2]+=tag[u];
		tag[u*2+1]+=tag[u];
	}
	sum[u]+=(UI)tag[u]*(R-L+1);
	tag[u]=0;
}
UI qry(int u,int L,int R,int l,int r)
{
	down(u,L,R);
	if (l<=L&&R<=r) return sum[u];
	int mid=(L+R)/2;
	UI ret=0;
	if (l<=mid) ret=qry(u*2,L,mid,l,r);
	if (r>mid) ret+=qry(u*2+1,mid+1,R,l,r);
	return ret;
}
void modi(int u,int L,int R,int l,int r,int x)
{
	if (l<=L&&R<=r)
	{
		tag[u]+=x;
		return;
	}
	down(u,L,R);
	int mid=(L+R)/2;
	if (l<=mid) modi(u*2,L,mid,l,r,x);
	if (r>mid) modi(u*2+1,mid+1,R,l,r,x);
	down(u*2,L,mid);
	down(u*2+1,mid+1,R);
	sum[u]=sum[u*2]+sum[u*2+1];
}
void solve(int L,int R,int l,int r)
{
	if (l==r)
	{
		for (int i=L;i<=R;i++)
			if (a[i].f==2) ans[a[i].id]=l;
		return;
	}
	int mid=(l+r)/2,n1=0,n2=0;
	UI x;
	for (int i=L;i<=R;i++)
		if (a[i].f==1)
		{
			if ((int)a[i].x>mid)
			{
				modi(1,1,n,a[i].l,a[i].r,1);
				c[++n2]=a[i];
			}
			else b[++n1]=a[i];
		}
		else
		{
			x=qry(1,1,n,a[i].l,a[i].r);
			if (x>=a[i].x) c[++n2]=a[i];
			else
			{
				a[i].x-=x;
				b[++n1]=a[i];
			}
		}
	for (int i=L;i<=R;i++)
		if (a[i].f==1&&(int)a[i].x>mid)
			modi(1,1,n,a[i].l,a[i].r,-1);
	for (int i=1;i<=n1;i++) a[L+i-1]=b[i];
	for (int i=1;i<=n2;i++) a[L+n1+i-1]=c[i];
	solve(L,L+n1-1,l,mid);
	solve(L+n1,R,mid+1,r);
}
int main()
{
	//freopen("b.in","r",stdin);
	//freopen("b.out","w",stdout);
	n=rdi();
	m=rdi();
	for (int i=1;i<=m;i++)
	{
		a[i].f=rdi();
		a[i].l=rdi();
		a[i].r=rdi();
		if (a[i].f==1) val[i]=ord[++o]=rdi();
		else a[i].x=rdu();
		a[i].id=i;
	}
	sort(ord+1,ord+o+1);
	o=unique(ord+1,ord+o+1)-ord-1;
	for (int i=1;i<=m;i++)
		if (a[i].f==1) a[i].x=lower_bound(ord+1,ord+o+1,val[i])-ord;
	solve(1,m,1,o);
	for (int i=1;i<=m;i++)
		if (ans[i]) printf("%d\n",ord[ans[i]]);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值