模板大全

O2/O3镇楼

#pragma GCC optimize(2)
#pragma GCC optimize(3)

Fread快读

在毒瘤题下能比 g e t c h a r getchar getchar快近 1 s 1s 1s

inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(ll &x){
    char ch=nc();x=0;
    while (!(ch>='0'&&ch<='9')) ch=nc();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=nc();
}

AC自动机,fail树(JZOJ 7044)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 1000005
#define ll long long
#include <vector>
using namespace std;
int trie[N][26],dfn[N],fail[N];
int f[N][3],q[N],size[N],cun[N],ys[N],len[N];
struct node{
	ll max,flag;
}tree[N<<1];
ll dp[N],val[N],s;
int i,j,k,m,n,o,p,l,t,tot,now,sum;
char c[N]; 
vector<int> a[N];
queue<int> h;
void build(int n)
{
	int now=0;
	for (int i=1;i<=n;i++)
	{
		if (!trie[now][c[i]-'a'])
			trie[now][c[i]-'a']=++sum;
		now=trie[now][c[i]-'a'],cun[++cun[0]]=now;
	}
}
void insert(int x,int y) {f[++t][1]=y,f[t][2]=q[x],q[x]=t;}
void work()
{
	int now=0;
	for (i=0;i<=25;i++)
		if (trie[now][i]) h.push(trie[now][i]);
	while (!h.empty())
	{
		int st=h.front();h.pop();
		for (int i=0;i<=25;i++)
			if (trie[st][i]) fail[trie[st][i]]=trie[fail[st]][i],h.push(trie[st][i]);
			else trie[st][i]=trie[fail[st]][i];
	}
	for (i=1;i<=sum;i++) insert(fail[i]+1,i+1);//printf("%d %d\n",fail[i],i);
}
void dg(int t)
{
	dfn[t]=++tot,size[t]=1;
	for (int k=q[t];k;k=f[k][2])
	{
		dg(f[k][1]);
		size[t]+=size[f[k][1]];
	}
}
ll max(ll a,ll b) {return a>b?a:b;}
void downdata(ll x)
{
	if (!tree[x].flag) return;
	ll k=tree[x].flag;
	tree[x<<1].max=max(tree[x<<1].max,k),tree[x<<1|1].max=max(tree[x<<1|1].max,k);
	tree[x<<1].flag=max(tree[x<<1].flag,k),tree[x<<1|1].flag=max(tree[x<<1|1].flag,k);
	tree[x].flag=0;
}
void change(ll x,ll l,ll r,ll st,ll en,ll ad)
{
	if (l>=st&&r<=en) tree[x].max=max(tree[x].max,ad),tree[x].flag=max(tree[x].flag,ad);
	else {
		downdata(x);
		ll mid=(l+r)/2;
		if (en<=mid) change(x<<1,l,mid,st,en,ad);
		else if (st>mid) change(x<<1|1,mid+1,r,st,en,ad);
		else change(x<<1,l,mid,st,mid,ad),change(x<<1|1,mid+1,r,mid+1,en,ad);
		tree[x].max=max(tree[x<<1].max,tree[x<<1|1].max);
	}
}
ll query(ll x,ll l,ll r,ll pos)
{
	if (l==r) return tree[x].max;
	else {
		downdata(x);
		ll mid=(l+r)/2;
		if (pos<=mid) return query(x<<1,l,mid,pos);
		else return query(x<<1|1,mid+1,r,pos);
	}
}
int main()
{
	freopen("word.in","r",stdin);
	freopen("word.out","w",stdout);
	scanf("%d\n",&n);
	for (i=1;i<=n;i++)
	{
		scanf("%s %lld\n",c+1,&val[i]);
		cun[0]=0;len[i]=strlen(c+1);
		build(len[i]);
		for (j=1;j<=cun[0];j++) a[i].push_back(cun[j]);
	} 
	work();
	dg(1);
	ll ans=0;
	for (i=1;i<=n;i++)
	{
		dp[i]=0;
		for (j=0;j<=len[i]-1;j++)
			dp[i]=max(dp[i],query(1,1,tot,dfn[a[i][j]+1]));
		dp[i]+=val[i];
		change(1,1,tot,dfn[a[i][len[i]-1]+1],dfn[a[i][len[i]-1]+1]+size[a[i][len[i]-1]+1]-1,dp[i]);
	}      
	for (i=1;i<=n;i++) ans=(dp[i]>ans?dp[i]:ans);
	printf("%lld\n",ans);
	return 0;
}

动态开点,求第K大,插入删除(JZOJ 4270)

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int i,j,k,m,n,o,p,l,s,t,x,y,tot;
const int inf=2147483647;
int root[27000001],num[27000001],left[27000001],right[27000001];
long long ans,sum[27000001];
char ch;
void add(int &x,int l,int r,int k,int bz)
{
	if (!x) tot++,x=tot;
	if (bz) num[x]++,sum[x]+=k;
	else num[x]--,sum[x]-=k;
	if (l==r) return;
	int mid=(l+r)/2;
	if (k<=mid) add(left[x],l,mid,k,bz); else add(right[x],mid+1,r,k,bz);
}
int find(int x,int l,int r,int k)
{
	if (l==r)
	{
		ans+=min(num[x],k)*l;
		return l;
	}
	int mid=(l+r)/2;
	if (num[right[x]]>=k) return find(right[x],mid+1,r,k);
	else {
		ans+=sum[right[x]];
		return find(left[x],l,mid,k-num[right[x]]);
	}
}
int main()
{
    freopen("grimoire.in","r",stdin);
    freopen("grimoire.out","w",stdout);
	scanf("%d%d\n",&n,&m);
	for (i=1;i<=m;i++)
	{
		scanf("%c",&ch);
		if (ch=='B')
		{
			scanf("ORROW %d %d\n",&x,&y);
			k=find(root[x],0,inf,x);
			add(root[x],0,inf,y,1);
			if (y>=k)
				add(root[0],0,inf,y,1),add(root[0],0,inf,k,0);
		} else {
			scanf("ETURN %d %d\n",&x,&y);
			k=find(root[x],0,inf,x+1);
			add(root[x],0,inf,y,0);
			if (y>=k)
				add(root[0],0,inf,y,0),add(root[0],0,inf,k,1);
		}
		ans=0;
		find(root[0],0,inf,n);
		printf("%lld\n",ans);
	}
	return 0;
}

匈牙利算法(二分图匹配 JZOJ 1156)

#include <cstdio>
#include <algorithm>
using namespace std;
int i,j,k,m,n,o,p,l,t;
int x[100001],y[100001];
bool line[201][201],bz[201];
int done[100001];
void insert(int x,int y)
{
	line[x][y]=true;
}
int find(int x)
{
	for (int i=1;i<=n;i++)
	{
		if (line[x][i]==true&&bz[i]==false)
		{
			bz[i]=true;
			if (!done[i]||find(done[i]))
			{
				done[i]=x;
				return true;
			}
		}
	}
	return false;
}
int main()
{
	scanf("%d",&n);
	for (i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
	scanf("%d",&m);
	for (i=1;i<=m;i++) {
		scanf("%d%d",&o,&p);
		if (x[o]<x[p]) line[o][p]=true;
		if (x[o]>x[p]) line[p][o]=true;
	}
	o=0;
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=n;j++) bz[j]=false;
		if (find(i)==true) o++;	
	}
	printf("%d\n",n-o);
}

树链剖分(JZOJ2256)

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
using namespace std;
int i,j,k,m,n,o,p,l,s,t,x,y,tot;
struct node{int sum,max,l,r;}f[1200001];
int ff[600001][3],q[600001],fa[300001],son[300001],dep[300001],size[300001];
int top[300001],tree[300001],pre[300001],a[300001];
char ch[7];
void insert(int x,int y)
{ t++,ff[t][1]=y,ff[t][2]=q[x],q[x]=t; }
void downdata(int x)
{
	int xx=x*2,yy=x*2+1;
	f[x].sum=f[xx].sum+f[yy].sum;
	f[x].max=max(f[xx].max,f[yy].max);
}
void change(int x,int v,int ad)
{
	if (f[x].l==f[x].r) f[x].max=ad,f[x].sum=ad;
	else {
		int mid=(f[x].l+f[x].r)/2;
		if (v<=mid) change(x*2,v,ad); else change(x*2+1,v,ad);
		downdata(x);
	}
}
void make(int x,int l,int r)
{
	f[x].l=l,f[x].r=r;
	if (l==r) f[x].sum=f[x].max=a[pre[l]];
	else {
		int mid=(l+r)/2;
		make(x*2,l,mid);make(x*2+1,mid+1,r);
		downdata(x);
	}
}
void dg1(int t)
{
	size[t]=1;
	for (int k=q[t];k;k=ff[k][2]) {
		int h=ff[k][1];
		if (h!=fa[t]) {
			fa[h]=t,dep[h]=dep[t]+1;
			dg1(h);
			size[t]+=size[h];
			if ((!son[t])||(size[son[t]]<size[h])) son[t]=h;
		}
	}
}
void dg2(int t,int ad)
{
	tot++;
	tree[t]=tot,pre[tot]=t,top[t]=ad;
	if (!son[t]) return;
	dg2(son[t],ad);
	for (int k=q[t];k;k=ff[k][2]) {
		int h=ff[k][1];
		if ((h!=fa[t])&&(h!=son[t])) dg2(h,h);
	}
}
int getsum(int t,int x,int y)
{
	if ((f[t].l>=x)&&(f[t].r<=y)) return f[t].sum;
	int mid=(f[t].l+f[t].r)/2,sum=0;
	if (x<=mid) sum+=getsum(t*2,x,y);
	if (y>mid) sum+=getsum(t*2+1,x,y);
	return sum;
}
int getmax(int t,int x,int y)
{
	if ((f[t].l>=x)&&(f[t].r<=y)) return f[t].max;
	int mid=(f[t].l+f[t].r)/2,Max=-2147483648;
	if (x<=mid) Max=max(Max,getmax(t*2,x,y));
	if (y>mid) Max=max(Max,getmax(t*2+1,x,y));
	return Max;
}
int findmax(int x,int y) 
{
	int xx=top[x],yy=top[y],maxans=-2147483648;
	while (xx!=yy) {
		if (dep[xx]<dep[yy]) swap(xx,yy),swap(x,y);
		maxans=max(maxans,getmax(1,tree[xx],tree[x]));
		x=fa[xx],xx=top[x];
	}	
	if (dep[x]>dep[y]) swap(x,y);
	maxans=max(maxans,getmax(1,tree[x],tree[y]));
	return maxans;
}
int findsum(int x,int y) 
{
	int xx=top[x],yy=top[y],sumans=0;
	while (xx!=yy) {
		if (dep[xx]<dep[yy]) swap(xx,yy),swap(x,y);
		sumans+=getsum(1,tree[xx],tree[x]);
		x=fa[xx],xx=top[x];
	}	
	if (dep[x]>dep[y]) swap(x,y);
	sumans+=getsum(1,tree[x],tree[y]);
	return sumans;
}
int main()
{
	scanf("%d",&n);
	for (i=1;i<=n-1;i++) {
		scanf("%d%d",&x,&y);
		insert(x,y);insert(y,x);
	}
	for (i=1;i<=n;i++) scanf("%d",&a[i]);
	t=0;dep[1]=1;
	dg1(1);
	dg2(1,1);
	make(1,1,n);
	scanf("%d",&m);
	for (i=1;i<=m;i++) {
		scanf("%s",&ch);
		scanf("%d%d",&x,&y);
		if (ch[1]=='H') {
			change(1,tree[x],y);
		} else {
			printf("%d\n",ch[1]=='M'?findmax(x,y):findsum(x,y));
		}
	}
}

线段树(区间查询,修改)(JZOJ1960)

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
int i,j,k,m,n,o,p,l,s,t,x,y,w,z;
long long ans;
long long tree[1000001],flag[1000001];
int a[1000001];
void down(int x)
{
	int k=flag[x];
	flag[x*2]+=k;flag[x*2+1]+=k;tree[x*2]+=k;tree[x*2+1]+=k;
	flag[x]=0;	
}
void make(int x,int l,int r)
{
	if (l==r) tree[x]=a[l];
	else {
		int mid=(l+r)/2;
		make(x*2,l,mid);make(x*2+1,mid+1,r);
		tree[x]=max(tree[x*2],tree[x*2+1]);
	}	
}
void change(int x,int l,int r,int zuo,int you,int h)
{
	if (l>=zuo&&r<=you) {
		tree[x]+=h;flag[x]+=h;return;
	}
	down(x);
	int mid=(l+r)/2;
	if (you<=mid) change(x*2,l,mid,zuo,you,h);
	else if (zuo>mid) change(x*2+1,mid+1,r,zuo,you,h);
	else change(x*2,l,mid,zuo,you,h),change(x*2+1,mid+1,r,zuo,you,h);
	tree[x]=max(tree[x*2],tree[x*2+1]);
}
void find(int x,int l,int r,int st,int en)
{
	if (l>=st&&r<=en) {
		ans=max(ans,tree[x]);return;
	} else {
		down(x);
		int mid=(l+r)/2;
		if (en<=mid) find(x*2,l,mid,st,en);
		else if (st>mid) find(x*2+1,mid+1,r,st,en);
		else find(x*2,l,mid,st,mid),find(x*2+1,mid+1,r,mid+1,en);
	}
}
int main()
{
	scanf("%d",&n);
	for (i=1;i<=n;i++) scanf("%d",&a[i]);
	make(1,1,n);
	scanf("%d",&m);
	for (i=1;i<=m;i++){
		scanf("%d",&z);
		if (z==2) {
			scanf("%d%d",&x,&y);
			ans=-2147483647;
			find(1,1,n,x,y);
			printf("%d\n",ans);
		} else {
			scanf("%d%d%d",&x,&y,&w);
			change(1,1,n,x,y,w);
		}
	}
	return 0;
}

Tarjan割点

#include<cstdio>
#include<cstring>
using namespace std;
struct node{
    int y,next;
}a[210000];int len,last[110000],bk[110000];
int dfn[110000],low[110000],sum=0,fa[110000],deep[110000];
int mymin(int x,int y) {return x<y?x:y;}
int ju(int x) {return x%2==1?x+1:x-1;}
void ins(int x,int y)
{
    a[++len].y=y;a[len].next=last[x];last[x]=len;
}
void dfs(int x,int ma)
{
    dfn[x]=low[x]=++sum;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dfn[y]==0) 
        {
            fa[y]=x;deep[y]=deep[x]+1;dfs(y,k);
            low[x]=mymin(low[x],low[y]);
        }
        else if(ju(ma)!=k) low[x]=mymin(low[x],low[y]);
    }
}
int x[110000],y[110000];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        ins(x[i],y[i]);ins(y[i],x[i]);
    }
    memset(dfn,0,sizeof(dfn));memset(deep,0,sizeof(deep));
    for(int i=1;i<=n;i++) if(dfn[i]==0) deep[i]=1,dfs(i,0);
    memset(bk,0,sizeof(bk));
    for(int i=1;i<=n;i++)
    {
        if(low[i]>=dfn[fa[i]]) bk[fa[i]]++;
    }
    for(int i=1;i<=n;i++)
    {
        if((deep[i]==1&&bk[i]>=2)||(deep[i]>1&&bk[i]>=1)) printf("%d\n",i);
    }
    return 0;
}

Tarjan求桥

#include<cstdio>
#include<cstring>
using namespace std;
int total,num,root;
int head[200001],next[200001],edge[200001],dfn[200001],low[200001];
bool bz[200001];
void add(int x,int y)
{
    total++;
    next[total]=head[x];
    head[x]=total;
    edge[total]=y;
}
void tarjan(int x,int ma)
{
    num++;
    dfn[x]=num;
    low[x]=num;
    int number=0;
    for (int i=head[x];i;i=next[i])
    {
        int y=edge[i];
        if (dfn[y]==0)
        {
            tarjan(y,i);
            if (low[x]>low[y])
            {
                low[x]=low[y];
            }
            if (dfn[x]<=low[y])
            {
                number++;
                if ((x!=root)||(number>1))
                {
                    bz[x]=true;
                }
            }
        }
        else
        {
            if ((y!=edge[ma^1])&&(low[x]>low[y]))
            {
                low[x]=low[y];
            }
        }
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    total=1;
    for (int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);   
    } 
    memset(bz,false,sizeof(bz)); 
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    num=0;
    for (int i=1;i<=n;i++)
    {
        if (dfn[i]==0)
        {
            root=i;
            tarjan(i,0);
        }
    }
    for (int i=1;i<=n;i++)
    {
        if (bz[i]==true)
        {
            printf("%d\n",i);   
        }   
    } 
}

网络流Dinic

#include<cstdio>
#include<cstring>
using namespace std;
int n,m,s,t,total,next[2000001],head[2000001],edge[2000001],v[2000001],h[2000001],d[2000001];
void insert(int x,int y,int z)
{
	total++;
	next[total]=head[x];
	head[x]=total;
	edge[total]=y;
	v[total]=z;
}
bool bfs()
{
	memset(d,0,sizeof(d));
	int l=1,r=1;
	h[1]=s;
	d[s]=1;
	while (l<=r)
	{
		int u=h[l];
		for (int i=head[u];i;i=next[i])
		{
			int y=edge[i];
			if (v[i]&&!d[y])
			{
				r++;
				h[r]=y;
				d[y]=d[u]+1;
				if (y==t) return true;
			}
		}
		l++;
	}
	return false;
}
int dinic(int k,int flow)
{
	if (k==t) return flow;
	int rest=flow;
	for (int i=head[k];i && rest;i=next[i])
	{
		int y=edge[i];
		if (v[i]&&d[y]==d[k]+1)
		{
			int cost;
			if (rest>v[i]) cost=v[i];
			else	cost=rest;
			int pay=dinic(y,cost);
			if (pay==0) d[y]=0;
			rest-=pay;
			v[i]-=pay;
			v[i^1]+=pay;
		}
	}
	return flow-rest;
}
int main()
{
	scanf("%d%d",&m,&n);
	s=1;
	t=n;
	total=1;
	for (int i=1;i<=m;i++)
	{
		int x1,y1,z1;
		scanf("%d%d%d",&x1,&y1,&z1);
		insert(x1,y1,z1);
		insert(y1,x1,0);
		insert(y1,x1,z1);
		insert(x1,y1,0);
	}
	int maxflow=0;
	int flow;
	while (bfs())
		while (flow=dinic(s,999999999)) maxflow+=flow;
	printf("%d",maxflow);
}

网络流SAP

ll dfs(ll t,ll flow)
{
	if (t==T) return flow;
	ll have=0;
	for (ll k=cur[t];k;k=f[k][2])
	{
		if (dis[f[k][1]]+1==dis[t]&&f[k][3])
		{
			cur[t]=k;
			ll now=dfs(f[k][1],min(flow-have,f[k][3]));
			f[k][3]-=now,f[k^1][3]+=now,have+=now;
			if (flow==have) return flow;
		}
	}
	cur[t]=q[t];
	if (!(--gap[dis[t]])) dis[S]=T; 
	++gap[++dis[t]];
	return have;
}

线筛( μ , φ \mu,\varphi μ,φ,质因数分解)

	mu[1]=phi[1]=1;
	for (R int i=2;i<=m;i++)
	{
		if (!bz[i]) pr[++pr[0]]=i,mu[i]=-1,phi[i]=i-1,mn[i]=i;
		for (R int j=1;j<=pr[0]&&pr[j]*i<=m;j++)
		{
			bz[i*pr[j]]=1,mn[i*pr[j]]=pr[j];
			if (!(i%pr[j])) {
				phi[i*pr[j]]=phi[i]*pr[j];break;
			}
			else mu[i*pr[j]]=-mu[i],phi[i*pr[j]]=phi[i]*(pr[j]-1);
		}
	}

ST表

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100005 
using namespace std;
int a[N];
int i,j,k,m,n,o,p,l,s,t,x,y;
struct node{
	int lg[N],st[N][18];
	int max(int a,int b) {return a>b?a:b;}
	void prepare() 
	{
		lg[0]=-1;
		for (int i=1;i<=n;i++) lg[i]=lg[i>>1]+1,st[i][0]=a[i];
		for (int i=1;i<=17;i++)
			for (int j=1;j+(1<<(i-1))<=n;j++)
				st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]); 
	}
	int query(int x,int y)
	{
		int k=lg[y-x+1];
		return max(st[x][k],st[y-(1<<k)+1][k]);
	}
}ST;
void read(int &x)
{
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
	freopen("Mourinho.in","r",stdin);
	freopen("Mourinho.out","w",stdout);
	read(n),read(m);
	for (i=1;i<=n;i++) read(a[i]);
	ST.prepare();
	for (i=1;i<=m;i++)
		read(x),read(y),printf("%d\n",ST.query(x,y));
	return 0;
}

多项式求逆,NTT JZOJ3303

#include<bits/stdc++.h>
#define G 3
#define ll long long
#define o3 inline
using namespace std;
int mod=1004535809;
int i,j,k,m,n,o,p,l,s,t,invG;
int f[2000001],inv[600001],fac[600001];
int a[600001],b[600001],c[600001],d[600001],r[600001];
o3 int ksm(int o,ll p)
{
	int s=1,t=o;
	while (p>0)
	{
		if (p%2) s=(ll)s*t%mod;
		t=(ll)t*t%mod,p/=2;
	}
	return s;
}
o3 int pow(int o,int p)
{
	int s=1,t=o;
	while (p>0)
	{
		if (p%2) s=(ll)s*t%mod;
		t=(ll)t*t%mod,p/=2;
	}
	return s;
}
o3 int NTT(int *f,int n,int op)
{
	for (register int i=0;i<n;i++)
		if (r[i]<i) swap(f[i],f[r[i]]);
	for (register int p=2;p<=n;p*=2)
	{
		int len=p/2,w=pow(op==1?G:invG,(mod-1)/p);
		for (register int k=0;k<n;k+=p)
		{
			int buf=1;
			for (register int i=k;i<k+len;i++)
			{
				int temp=(ll)f[len+i]*buf%mod;
				f[len+i]=(f[i]-temp+mod)%mod;
				f[i]=(f[i]+temp)%mod;buf=(ll)buf*w%mod;
			}
		}
	}
	if (op==-1)
	{
		int invN=pow(n,mod-2);
		for (register int i=0;i<n;i++) f[i]=(ll)f[i]*invN%mod;
	}
}
o3 void getni(int deg,int *a,int *b,int *tmp)
{
	if (deg==1) {
		b[0]=pow(a[0],mod-2);return;
	}
	getni((deg+1)/2,a,b,tmp);
	int m=1;while (m<deg*2) m*=2;
	memset(r,0,sizeof(r));
	copy(a,a+deg,tmp);fill(tmp+deg,tmp+m,0);
    for (register int i=1;i<m;i++) 
    {
		r[i]=((r[i>>1]>>1)|((i&1)*(m>>1)));
	}
	NTT(tmp,m,1);
	NTT(b,m,1);
	for (register int i=0;i<m;i++)
	{
		b[i]=(ll)b[i]*(2-(ll)b[i]*tmp[i]%mod)%mod;
		if (b[i]<0) b[i]+=mod;
	}
	NTT(b,m,-1);fill(b+deg,b+m,0);
}
int main()
{
	scanf("%d",&n);
	invG=pow(G,mod-2);
	m=1;while (m<n*2) m*=2;
	fac[0]=fac[1]=inv[0]=inv[1]=1;
	for (i=1;i<=m;i++) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=(ll)inv[i-1]*pow(i,mod-2)%mod;
	d[0]=0;a[0]=a[1]=d[1]=1;
	for (i=2;i<=n;i++) 
	{
		ll ggg=i;ggg=ggg*(ggg-1)/2;
		a[i]=(ll)ksm(2,ggg)*inv[i]%mod;
	}
	getni(m,a,b,c);
	for (i=2;i<=n;i++) {
		ll ggg=i;ggg=ggg*(ggg-1)/2;
		d[i]=(ll)ksm(2,ggg)*inv[i-1]%mod;
	}
  	for (int i=1;i<=m;i++)
   		r[i]=(r[i>>1]>>1)|(i&1?m>>1:0);
	NTT(b,m,1),NTT(d,m,1);
	for (int i=0;i<=m;i++) b[i]=(ll)b[i]*d[i]%mod;
	NTT(b,m,-1);
	long long ans=(ll)b[n]*fac[n-1]%mod;
	printf("%lld\n",ans);
	return 0;
}

洛谷FFT板子P3803

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <complex>
#include <cmath>
#define N 2100005
using namespace std;
const double Pi=acos(-1);
int i,j,k,m,n,o,p,l,s,t;
complex<double> a[N],b[N];
int r[N];
void read_double(complex<double> &x)
{
	char ch=getchar();x=0;int f=(ch=='-'?-1:1);
	while (ch<'0'||ch>'9') ch=getchar(),f=(ch=='-'?-1:f);
	while (ch>='0'&&ch<='9') x=x.real()*10+ch-48,ch=getchar();
	x*=f;
}
void read_int(int &x)
{
	char ch=getchar();x=0;int f=(ch=='-'?-1:1);
	while (ch<'0'||ch>'9') ch=getchar(),f=(ch=='-'?-1:f);
	while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
	x*=f;
}
void FFT(complex<double> *a,int opt)
{
	for (int i=0;i<n;i++)
		if (i<r[i]) swap(a[i],a[r[i]]);
	for (int i=1;i<n;i<<=1)
	{
		complex<double> W(cos(Pi/i),opt*sin(Pi/i));
		for (int p=i<<1,j=0;j<n;j+=p)
		{
			complex<double> w(1,0);
			for (int k=0;k<i;k++,w*=W)
			{
				complex<double> x=a[j+k],y=a[i+j+k]*w;
				a[j+k]=x+y,a[i+j+k]=x-y;
			}
		}
	}
}
int main()
{
	read_int(n),read_int(m);
	for (i=0;i<=n;i++) read_double(a[i]);
	for (i=0;i<=m;i++) read_double(b[i]);
	m+=n;
	for (n=1;n<=m;n<<=1) l++;
	for (i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
	FFT(a,1),FFT(b,1);
	for (i=0;i<=n;i++) a[i]=a[i]*b[i];
	FFT(a,-1);
	for (i=0;i<=m;i++) 
		printf("%.0lf ",floor(a[i].real()/n+0.5));
	return 0;
}
 

F W T   o r   a n d   x o r FWT\,or\,and\,xor FWTorandxor 洛谷P4717

#include <cstdio>
#include <cstring>
#include <algorithm>
#define mo 998244353
#define inv2 499122177
#define ll long long
#define N 1000005
using namespace std;
ll f[N],g[N],a[N],b[N];
ll i,j,k,m,n,o,p,l,s,t;
void FWT_or(ll *a,ll opt)
{
	for (ll i=1;i<n;i<<=1)
		for (ll p=i<<1,j=0;j<n;j+=p)
			for (ll k=0;k<i;k++)
				a[i+j+k]+=a[j+k]*opt,a[i+j+k]=(a[i+j+k]+mo)%mo;
}
void FWT_and(ll *a,ll opt)
{
	for (ll i=1;i<n;i<<=1)
		for (ll p=i<<1,j=0;j<n;j+=p)
			for (ll k=0;k<i;k++)
				a[j+k]+=a[i+j+k]*opt,a[j+k]=(a[j+k]+mo)%mo;
}
void FWT_xor(ll *a,ll opt)
{
	for (ll i=1;i<n;i<<=1)
		for (ll p=i<<1,j=0;j<n;j+=p)
			for (ll k=0;k<i;k++)
			{
				ll x=a[j+k],y=a[i+j+k];
				a[j+k]=(x+y)%mo,a[i+j+k]=(x-y+mo)%mo;
				if (opt==-1) a[j+k]=a[j+k]*inv2%mo,a[i+j+k]=a[i+j+k]*inv2%mo;	
			}
}
void read(ll &x)
{
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
	freopen("FWT.in","r",stdin);
	freopen("FWT.out","w",stdout);
	read(n);n=1<<n;
	for (i=0;i<n;i++) read(f[i]);
	for (i=0;i<n;i++) read(g[i]);
	memcpy(a,f,sizeof(a)),memcpy(b,g,sizeof(b));
	FWT_or(f,1),FWT_or(g,1);
	for (i=0;i<n;i++) f[i]=f[i]*g[i]%mo;
	FWT_or(f,-1);
	for (i=0;i<n;i++) printf("%lld ",f[i]);
	puts("");
	memcpy(f,a,sizeof(f)),memcpy(g,b,sizeof(g));
	FWT_and(f,1),FWT_and(g,1);
	for (i=0;i<n;i++) f[i]=f[i]*g[i]%mo;
	FWT_and(f,-1);
	for (i=0;i<n;i++) printf("%lld ",f[i]);
	puts("");
	memcpy(f,a,sizeof(f)),memcpy(g,b,sizeof(g));
	FWT_xor(f,1),FWT_xor(g,1);
	for (i=0;i<n;i++) f[i]=f[i]*g[i]%mo;
	FWT_xor(f,-1);
	for (i=0;i<n;i++) printf("%lld ",f[i]);
	puts("");
	return 0;
}

splay 普通平衡树洛谷P3369

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node{
	int size,cnt,key,fa;
}tree[1000001];
int son[1000001][2];
int i,j,k,m,n,o,p,l,s,t,root,len,ihds;
void clear(int x) {tree[x].size=tree[x].cnt=tree[x].key=tree[x].fa=0;son[x][0]=son[x][1]=0;}
void update(int x)
{
	if (!x) return;
	tree[x].size=tree[x].cnt;
	if (son[x][0]) tree[x].size+=tree[son[x][0]].size;
	if (son[x][1]) tree[x].size+=tree[son[x][1]].size;
}
int get(int x) {return son[tree[x].fa][1]==x;}
void rotate(int x)
{
	int fa=tree[x].fa,grandpa=tree[fa].fa,wx=get(x),wfa=grandpa&&get(fa);
	son[fa][wx]=son[x][wx^1],tree[son[fa][wx]].fa=fa;
	son[x][wx^1]=fa,tree[fa].fa=x;tree[x].fa=grandpa;
	if (grandpa) son[grandpa][wfa]=x;
	update(fa);update(x);
} 
void splay(int x)
{
	for (int fa;fa=tree[x].fa;rotate(x))
	{
		if (tree[fa].fa) rotate(get(x)==get(fa)?fa:x);
	}
	root=x;
}
void insert(int x)
{
	if (!root) {
		len++,tree[1].fa=0;tree[1].size=tree[1].cnt=1;tree[1].key=x,son[1][0]=son[1][1]=0,root=1;
	} else {
		int now=root,fa;
		while (1)
		{
			if (x==tree[now].key)
			{
				tree[now].cnt++;update(now),update(tree[now].fa);splay(now);break;
			}
			fa=now,now=son[now][tree[now].key<x];
			if (!now)
			{
				len++,tree[len].fa=fa,tree[len].size=tree[len].cnt=1;tree[len].key=x;son[len][0]=son[len][1]=0;son[fa][tree[fa].key<x]=len;update(fa);splay(len);break;
			}
		} 
	}
} 
int queryrank(int x)
{
	int now=root,ans=0;
	while (1)
	{
		if (tree[now].key>x) now=son[now][0];
		else {
			ans+=tree[son[now][0]].size;
			if (tree[now].key==x) {splay(now);return ans+1;}
			ans+=tree[now].cnt,now=son[now][1];
		}	
	}	
} 
int querynumber(int x)
{
	int now=root;
	while (1)
	{
		if (son[now][0]&&tree[son[now][0]].size>=x) now=son[now][0];
		else {
			int comp=tree[son[now][0]].size+tree[now].cnt;
			if (x<=comp) return tree[now].key;
			x-=comp,now=son[now][1];
		} 
	}
}
int pre()
{
	int now=root;
	now=son[now][0];
	while (son[now][1]) now=son[now][1];
	return now;
}
int nxt()
{
	int now=root;
	now=son[now][1];
	while (son[now][0]) now=son[now][0];
	return now;
}
void del(int x)
{
	queryrank(x);
	if (tree[root].cnt>1) {tree[root].cnt--;update(root);return;} 
	if (!son[root][0]&&!son[root][1]) {clear(root);root=0;return;}
	if (!son[root][0]) 
	{
		int oldroot=root;root=son[root][1];tree[root].fa=0;clear(oldroot);return;	
	} else if (!son[root][1])
	{
		int oldroot=root;root=son[root][0];tree[root].fa=0;clear(oldroot);return;
	}
	int pr=pre(),oldroot=root;splay(pr);
	son[pr][1]=son[oldroot][1],tree[son[oldroot][1]].fa=root;clear(oldroot);update(root);
}
int main()
{
	freopen("splay.in","r",stdin);
	freopen("splay.out","w",stdout);
	scanf("%d",&t);
	while (t--)
	{
		scanf("%d%d",&o,&p);
		if (p==3)
		{
			int fdsa=0;
		}
		if (o==1) insert(p);
		else if (o==2) del(p);
		else if (o==3) printf("%d\n",queryrank(p));
		else if (o==4) printf("%d\n",querynumber(p));
		else if (o==5) insert(p),
		printf("%d\n",tree[pre()].key),del(p);
		else if (o==6) insert(p),printf("%d\n",tree[nxt()].key),del(p); 
	}
	return 0;
}

替罪羊树 普通平衡树洛谷P3369

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000005
using namespace std;
struct node{
	int x,zuo,you,fa,size,trsize,whsize,tot;bool tf;
}tree[N];
struct wyd{
	int x,tot;
}shulie[N];
int ck[N];
int i,j,k,m,n,o,p,l,s,t,tt,len,root,x,y;
double alpha=0.75;
void updata(int now,int x,int y,int z)
{
	if (!now) return;
	tree[now].trsize+=x;tree[now].size+=y,tree[now].whsize+=z;
	updata(tree[now].fa,x,y,z);
}
int kk()
{
	return t>0?ck[t--]:++len;
}
int find(int x,int now)
{
	if (x<tree[now].x&&tree[now].zuo) return find(x,tree[now].zuo);
	if (x>tree[now].x&&tree[now].you) return find(x,tree[now].you);
	return now; 
}
int build(int x,int now,int fa)
{
	tree[now].x=x;tree[now].zuo=tree[now].you=0;tree[now].fa=fa;
	tree[now].size=tree[now].trsize=tree[now].whsize=tree[now].tot=1;
	tree[now].tf=false;
}
void dfs_rebuild(int now)
{
	if (!now) return;
	dfs_rebuild(tree[now].zuo);
	if (!tree[now].tf) 
	{
		shulie[++tt].x=tree[now].x,shulie[tt].tot=tree[now].tot;
	}
	ck[++t]=now;
	dfs_rebuild(tree[now].you);
}
int readd(int l,int r,int fa)
{
	if (o==5)
	{
		o=o;
	}
	if (l>r) return 0;
	int mid=(l+r)/2;int now=kk();
	tree[now].fa=fa;
	tree[now].x=shulie[mid].x;
	tree[now].tot=shulie[mid].tot;
	tree[now].zuo=readd(l,mid-1,now);
	tree[now].you=readd(mid+1,r,now);
	tree[now].size=tree[now].trsize=r-l+1;
	tree[now].whsize=tree[tree[now].zuo].whsize+tree[tree[now].you].whsize+shulie[mid].tot;
	tree[now].tf=false;
	return now;
}
void rebuild(int x)
{
	tt=0;
	dfs_rebuild(x);
	if (x==root) {
		root=readd(1,tt,0);return;
	}
	updata(tree[x].fa,tree[x].trsize-tree[x].size,0,0);
	if (tree[tree[x].fa].zuo==x) tree[tree[x].fa].zuo=readd(1,tt,tree[x].fa);
	else tree[tree[x].fa].you=readd(1,tt,tree[x].fa);
}
void find_rebuild(int now,int x)
{
	if ((double)tree[tree[now].zuo].size>(double)tree[now].size*alpha||
	(double)tree[tree[now].you].size>(double)tree[now].size*alpha||
	(double)tree[now].size-(double)tree[now].trsize>(double)tree[now].size*0.3)
	{
		rebuild(now);
		return;
	}
	if (tree[now].x!=x)
		find_rebuild(x<tree[now].x?tree[now].zuo:tree[now].you,x);
}
void add(int x)
{
	if (root==0)
	{
		build(x,root=kk(),0);
		return;
	}
	int p=find(x,root);
	if (x==tree[p].x)
	{
		tree[p].tot++;
		if (tree[p].tf) tree[p].tf=false,updata(p,1,0,1);
		else updata(p,0,0,1);
	}
	else if (x<tree[p].x) build(x,tree[p].zuo=kk(),p),updata(p,1,1,1);
	else build(x,tree[p].you=kk(),p),updata(p,1,1,1);
	find_rebuild(root,x);
}
void del(int x)
{
	if (o==18)
	{
		o=o;
	} 
	int p=find(x,root);
	tree[p].tot--;
	if (!tree[p].tot) updata(p,-1,0,-1),tree[p].tf=true;
	else updata(p,0,0,-1);
	find_rebuild(root,x);
}
int findxpm(int x)
{
	int now=root,ans=0;
	while (tree[now].x!=x)
	{
		if (x<tree[now].x) now=tree[now].zuo;
		else ans+=tree[now].tot+tree[tree[now].zuo].whsize,now=tree[now].you;
	} 
    ans+=tree[tree[now].zuo].whsize;
	return ans+1;
}
int findmpx(int x)
{
	if (o==42)
	{
		o=o;
	 } 
	int now=root;
	while (0<1)
	{
		if (x<=tree[tree[now].zuo].whsize) now=tree[now].zuo;
		else {
			x-=tree[tree[now].zuo].whsize;
			if (tree[now].tot>=x)
			{
				return tree[now].x;
			}x-=tree[now].tot;
			now=tree[now].you;
		}
	}
}
int pre(int x)
{
	add(x);
	int tmp=findxpm(x);
	del(x);
	return findmpx(tmp-1);
}
int nxt(int x)
{
	add(x+1);
	int tmp=findxpm(x+1);
	del(x+1);
	return findmpx(tmp);
}
int main()
{
	scanf("%d",&o);
	while (o--)
	{
		scanf("%d%d",&x,&y);
		if (x==1) add(y);
		if (x==2) del(y);
		if (o==42)
		{
			o=o;
		}
		if (x==3) printf("%d\n",findxpm(y));
		if (x==4) printf("%d\n",findmpx(y));
		if (x==5) printf("%d\n",pre(y));
		if (x==6) printf("%d\n",nxt(y));
	}
	return 0;
}

费用流 洛谷P2045K取方格数

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int f[200005][5],q[10005];
int dist[10005],flow[10005],spfa[10005],pre[10005],last[10005];
int i,j,k,m,n,o,p,l,s,t,S,T,times,c,ans;
void insert(int x,int y,int z,int w) {
	f[++t][1]=y,f[t][2]=q[x],f[t][3]=z,f[t][4]=w,q[x]=t;
	f[++t][1]=x,f[t][2]=q[y],f[t][3]=0,f[t][4]=-w,q[y]=t;
}
int num(int x,int y,int z) {return x*n*n+(y-1)*n+z;}
int costflow()
{
	queue<int>h;
	memset(dist,-1,sizeof(dist));memset(spfa,0,sizeof(spfa));
	h.push(S);flow[S]=1e9;dist[S]=0;spfa[S]=1;
	while (!h.empty())
	{
		int st=h.front();h.pop();
		for (int k=q[st];k;k=f[k][2])
		{
			if (!f[k][3]) continue;
			if (dist[st]+f[k][4]>dist[f[k][1]])
			{
				dist[f[k][1]]=dist[st]+f[k][4];
				flow[f[k][1]]=min(flow[st],f[k][3]);pre[f[k][1]]=k;
				if (!spfa[f[k][1]]) h.push(f[k][1]),spfa[f[k][1]]=1;	
			}	
		}spfa[st]=0;
	}
	return dist[T]!=-1;
}
void update()
{
	ans+=dist[T]*flow[T];
	int k=T;
	while (k!=S)
	{
		f[pre[k]][3]-=flow[T];
		f[pre[k]^1][3]+=flow[T];
		k=f[pre[k]^1][1];
	}
}
int read(int &x)
{
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
	read(n),read(times);t=1;
	for (i=1;i<=n;i++)
		for (j=1;j<=n;j++)
		{
			read(c);
			insert(num(0,i,j),num(1,i,j),1,c);
			insert(num(0,i,j),num(1,i,j),times-1,0);
			if (i<n) insert(num(1,i,j),num(0,i+1,j),times,0);
			if (j<n) insert(num(1,i,j),num(0,i,j+1),times,0); 
		}
	S=1,T=2*n*n;
	while (costflow()) 
		update();
	printf("%d\n",ans);
	return 0;
}

高斯消元 JZOJ6942作业题,也涉及FWT,矩阵树定理

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define mo 998244353
#define inv2 499122177
using namespace std;
ll i,j,k,m,n,o,p,l,s,t,ans;
struct node{
	ll x,y,z; 
}a[10005];
ll b[10005][513],c[513],d[513];
ll f[65][65];
void FWT(ll *a,ll opt)
{
    for (ll i=1;i<256;i<<=1)
        for (ll p=i<<1,j=0;j<256;j+=p)
            for (ll k=0;k<i;++k)
            {
                ll X=a[j+k],Y=a[i+j+k];
                a[j+k]=X+Y;a[i+j+k]=(X-Y+mo)%mo;
                if (opt==-1)
					a[j+k]=a[j+k]*inv2%mo,a[i+j+k]=a[i+j+k]*inv2%mo;
            }
}
void read(ll &x)
{
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
void add(ll x,ll y,ll z) 
{
	f[x][x]+=z,f[x][y]+=-z;f[x][x]%=mo,f[x][y]%=mo;//血泪教训,这里一定要取模!
}
int main()
{
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	read(n),read(m);
	for (i=1;i<=m;i++) read(a[i].x),read(a[i].y),read(a[i].z);
	for (i=1;i<=m;i++)
	{
		memset(c,0,sizeof(c));
		c[a[i].z]=1;
		FWT(c,1);
		memcpy(b[i],c,sizeof(b[i]));
	}
	for (p=0;p<=255;p++)
	{
		if (p==15)
		{
			int sfgx=0;
		}
		memset(f,0,sizeof(f));
		for (i=1;i<=m;i++) 
			add(a[i].x,a[i].y,b[i][p]),add(a[i].y,a[i].x,b[i][p]);
		s=1;
		for (i=1;i<=n-1;i++)
		{
			for (j=i+1;j<=n-1;j++)
			{
				while (f[j][i])
				{
					o=f[i][i]/f[j][i];
					for (k=i;k<=n-1;k++)
						f[i][k]=(f[i][k]-(o*f[j][k]%mo)+mo)%mo;
					swap(f[i],f[j]);
					s=-s;
				}
			}
			s=s*f[i][i]%mo;
		}
		d[p]=s;
	}
	FWT(d,-1);
	for (i=0;i<=255;i++) 
		ans=(ans+(i*d[i]%mo)+mo)%mo;
	printf("%lld\n",ans);
	return 0;
}

SAM TJOI2015弦论

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dep[1000001],fa[1000001],t[1000001][27];
int f[1000001],b[1000001],sum[1000001],g[1000001];
char c[1000001];
int i,j,k,m,n,o,p,l,s,last,q,tot,opt;
int push(int x) {dep[++tot]=x;return tot;} 
void ins(int c)
{
	int np=push(dep[last]+1),p=last;g[np]=1;
	for (;p&&!t[p][c];p=fa[p]) t[p][c]=np;
	if (!p) fa[np]=1;
	else {
		int q=t[p][c];
		if (dep[q]==dep[p]+1) fa[np]=q;
		else {
			int nq=push(dep[p]+1);
			fa[nq]=fa[q],fa[q]=fa[np]=nq;
			memcpy(t[nq],t[q],sizeof(t[nq]));
			for (;p&&t[p][c]==q;p=fa[p]) t[p][c]=nq;
		}
	}last=np;
}
int work(int k)
{
	int x=1;
	while (1)
	{
		if (k<=g[x]) return 0;k-=g[x];
		for (int i=0;i<=25;i++)
		{
			if (!t[x][i]) continue;
			if (k<=sum[t[x][i]])
			{
				putchar('a'+i);
				x=t[x][i];break;
			}k-=sum[t[x][i]];
		}
	}
}
int main()
{
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout); 
	scanf("%s\n",c+1);
	scanf("%d%d",&opt,&k);tot=last=1;n=strlen(c+1);
	for (i=1;i<=n;i++) 
	{
		ins(c[i]-'a');
	}
	for (i=1;i<=tot;i++) b[dep[i]]++;
	for (i=1;i<=n;i++) b[i]+=b[i-1];
	for (i=tot;i>=1;i--) f[b[dep[i]]--]=i;
	for (i=tot;i>=1;i--)
	{
		if (opt) g[fa[f[i]]]+=g[f[i]];
		else g[f[i]]=1;
	}g[1]=0;
	for (i=tot;i>=1;i--)
	{
		for (j=0;j<=25;j++) sum[f[i]]+=sum[t[f[i]][j]];
		sum[f[i]]+=g[f[i]];
	}
	if (sum[1]<k)
	{
		puts("-1");return 0;
	}
	work(k);
	return 0; 
}

PAM JZOJ3291【JSOI2013】快乐的JYY

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int i,j,k,m,n,o,p,l,s,t;
struct node{
	int son[26],sum1,sum2,fa,len;
}pam[100005];
char a[100005],b[100005];
int i,j,k,m,n,o,p,l,s,t,tot,last;
long long ans;
void insert(char c,int n)
{
	int p=last;
	while (a[n-pam[p].len-1]!=a[n]) p=pam[p].fa;
	if (!pam[p].son[c])
	{
		int q=++tot,Fa=pam[p].fa;
		pam[q].len=pam[p].len+2,pam[p].son[c]=q;
		while (a[n-pam[Fa].len-1]!=a[n]) Fa=pam[Fa].fa;
		pam[q].fa=pam[Fa].son[c];
	}
	last=pam[p].son[c],pam[last].sum1++;
}
void find(char c,int n)
{
	int p=last;
	while (p!=1&&(a[n-pam[p].len-1]!=a[n]||!pam[p].son[c])) p=pam[p].fa;
	if (p==1)
	{
		last=1;return;
	}
	last=pam[p].son[c],pam[last].sum2++; 
}
int main()
{
	scanf("%s\n",a+1),n=strlen(a+1);
	scanf("%s\n",b+1),m=strlen(b+1);
	a[0]='#',b[0]='#';tot=1,pam[0].len=-1,pam[0].fa=1;
	for (i=1;i<=n;i++) insert(a[i]-'A',i);
	last=0;
	for (i=1;i<=m;i++) find(b[i]-'A',i);
	for (i=tot;i>=2;i--) pam[fa[i]].sum1+=pam[i].sum1,pam[fa[i]].sum2+=pam[i].sum2,ans+=1ll*pam[i].sum1*pam[i].sum2;
	printf("%lld\n",ans);
} 

马拉车 洛谷P3805

#include <cstdio> 
#include <cstring>
#include <algorithm>
using namespace std;
char s[30000005],a[12000005];
int p[32000005];
int i,j,k,m,n,o,l,t,len,mid,mx,ans;
int main()
{
//	freopen("manacher.in","r",stdin);
//	freopen("manacher.out","w",stdout);
	scanf("%s",a+1);
	int len=strlen(a+1);
	s[0]='(';s[1]='#';l=1;
	for (i=1;i<=len;i++) s[++l]=a[i],s[++l]='#';
	s[++l]=')';len=l;
	mid=mx=ans=1;
	for (i=1;i<len;i++)
	{
		if (i<mx) p[i]=min(p[mid*2-i],mx-i);
		else p[i]=1;
		while (s[i-p[i]]==s[i+p[i]]) p[i]++;
		if (i+p[i]>mx) mx=i+p[i],mid=i;
		ans=max(ans,p[i]-1); 
		printf("%d %c\n",p[i]-1,s[i]);
	} 
	printf("%d\n",ans);
}

莫比乌斯函数——一些小小的证明

普通莫队——小Z的袜子JZOJ1902

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
struct node{
	long long l,r,a,b,id;
}q[100005];
long long a[100005],sum[100005],b[100005];
long long i,j,k,m,n,o,p,l,s,t,unit,r,ans;
bool cmpx(node x,node y)
{
	return b[x.l]==b[y.l]?x.r<y.r:x.l<y.l;
}
long long work(long long x,long long add)
{
	ans-=sum[a[x]]*sum[a[x]],sum[a[x]]+=add,ans+=sum[a[x]]*sum[a[x]];
}
long long getgcd(long long x,long long y)
{
	return !(x%y)?y:getgcd(y,x%y);
}
long long cmpy(node x,node y)
{
	return x.id<y.id;
}
int main()
{
	freopen("socks.in","r",stdin);
	freopen("socks.out","w",stdout);
	scanf("%lld%lld",&n,&m);unit=sqrt(n);
	for (i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=i/unit+1;
	for (i=1;i<=m;i++) scanf("%lld%lld",&q[i].l,&q[i].r),q[i].id=i;
	sort(q+1,q+m+1,cmpx);l=1,r=0;
	for (i=1;i<=m;i++)
	{
		while (l<q[i].l) work(l,-1),l++;
		while (l>q[i].l) work(l-1,1),l--;
		while (r<q[i].r) work(r+1,1),r++;
		while (r>q[i].r) work(r,-1),r--;
		if (q[i].l==q[i].r) {
			q[i].a=0,q[i].b=1;continue;
		}long long len=q[i].r-q[i].l+1;
		q[i].a=ans-len;q[i].b=len*(len-1);
		long long gcd=getgcd(q[i].a,q[i].b);
		q[i].a/=gcd,q[i].b/=gcd;
		
	}
	sort(q+1,q+m+1,cmpy);
	for (i=1;i<=m;i++) printf("%lld/%lld\n",q[i].a,q[i].b);
	return 0;
}

树上莫队 JZOJ3360苹果树

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int block[100001],dfn[100001],sta[100001];
int f[200001][4],q[200001],ans[200001],co[200001];
int b[200001][17],mi[200001],num[200001],dep[200001];
bool a[100001];
struct node{
	int x,y,a,b,id;
}que[100005];
int i,j,k,m,n,o,p,l,s,t,sum,now,tot,root,top,bg,g;
void insert(int x,int y)
{
	f[++t][1]=y,f[t][2]=q[x],q[x]=t;
}
int dg(int t,int fa)
{
	int size=0;
	dfn[t]=++tot;
	for (int k=q[t];k;k=f[k][2])
	{
		if (f[k][1]==fa) continue;b[f[k][1]][0]=t,dep[f[k][1]]=dep[t]+1;
		size+=dg(f[k][1],t);
		if (size>=bg)
		{
			g++;
			for (int k=1;k<=size;k++) block[sta[top--]]=g;
			size=0;
		}
	}
	sta[++top]=t;
	return size+1;
}
bool cmp(node a,node b)
{
	return (block[a.x]==block[b.x]?dfn[a.y]<dfn[b.y]:block[a.x]<block[b.x]);
}
int getlca(int x,int y)
{
	if (dep[x]<dep[y]) swap(x,y);
	int k=dep[x]-dep[y];
	for (int i=16;i>=0;i--)
	{
		if (k>=mi[i]) k-=mi[i],x=b[x][i];	
	}	
	if (x==y) return x;
	for (int i=16;i>=0;i--)
	{
		if (b[x][i]!=b[y][i]) x=b[x][i],y=b[y][i];
	}
	return b[x][0];
} 
void work(int x)
{
	if (!a[x]) now+=(++num[co[x]]==1);
	else now-=(--num[co[x]]==0);
	a[x]^=1;
}
void change(int x,int y)
{
	while (x!=y)
	{
		if (dep[x]>dep[y]) work(x),x=b[x][0];
		else work(y),y=b[y][0]; 
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++) scanf("%d",&co[i]);
	for (i=1;i<=n;i++)
	{
		scanf("%d%d",&o,&p);
		if (!(o*p)) root=o+p;
		else insert(o,p),insert(p,o);
	}
	bg=sqrt(n);dg(root,0);g++;
	while (top) block[sta[top--]]=g;mi[0]=1;
	for (i=1;i<=16;i++)
	{
		mi[i]=mi[i-1]*2;
		for (j=1;j<=n;j++) b[j][i]=b[b[j][i-1]][i-1];
	}
	for (i=1;i<=m;i++) scanf("%d%d%d%d",&que[i].x,&que[i].y,&que[i].a,&que[i].b),que[i].id=i;
	sort(que+1,que+m+1,cmp);
	int x=root,y=root;now=0;
	for (i=1;i<=m;i++)
	{
		if (x!=que[i].x) change(x,que[i].x),x=que[i].x;
		if (y!=que[i].y) change(y,que[i].y),y=que[i].y;
		k=getlca(x,y);work(k);
		if ((que[i].a==que[i].b)||(!(num[que[i].a]*num[que[i].b]))) ans[que[i].id]=now;
		else ans[que[i].id]=now-1;work(k);
	}
	for (i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

圆方树上最短路 JZOJ1914

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int sum[400005],bh[400005],co[400005],dfn[400005],len[400005],dis[400005],sta[400005],f[500005][4],q[100005],dep[100005],bz[400005],vis[400005],b[100005][18],mi[18];
int i,j,k,m,n,o,p,l,s,T=1,x,y,z,times,tot,xx,yy;
queue<int> h;
void insert(int x,int y,int z) {f[++T][1]=y,f[T][2]=q[x],f[T][3]=z,q[x]=T;}
void read(int &x)
{
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
void dg(int t)
{
	dfn[t]=++tot;sta[++sta[0]]=t;
	for (int k=q[t];k;k=f[k][2])
	{
		if (vis[k]||vis[k^1]||k>2*m+1) continue;
		if (!dfn[f[k][1]]) 
			len[f[k][1]]=len[t]+f[k][3],bh[f[k][1]]=k,vis[k]=vis[k^1]=1,dg(f[k][1]);
		else {
			if (dfn[f[k][1]]>=dfn[t]) continue;
			co[f[k][1]]=++co[0];bz[k]=bz[k^1]=1;sum[co[0]]=f[k][3];
			for (int i=t;i!=f[k][1];i=f[bh[i]^1][1])
			{
				bz[bh[i]]=bz[bh[i]^1]=1,sum[co[0]]+=f[bh[i]^1][3];
				co[i]=co[0];insert(f[k][1],i,0),insert(i,f[k][1],0);
			}
		} 
	}
}
void dfs(int t)
{
	for (int k=q[t];k;k=f[k][2])
	{
		if (vis[k]||bz[k]) continue;
		vis[k]=vis[k^1]=1;
		dep[f[k][1]]=dep[t]+1;b[f[k][1]][0]=t;
		dfs(f[k][1]);	
	} 
}
int lca(int &x,int &y)
{
	if (dep[x]<dep[y]) swap(x,y);
	int k=dep[x]-dep[y];
	for (int i=17;i>=0;i--)
		if (k>=mi[i]) k-=mi[i],x=b[x][i];
	if (x==y) return x;
	for (int i=17;i>=0;i--)
		if (b[x][i]!=b[y][i]) x=b[x][i],y=b[y][i];
	return b[x][0];
}
int main()
{
	freopen("garden.in","r",stdin);
	freopen("garden.out","w",stdout);
	read(n),read(m);
	for (mi[0]=i=1;i<=17;i++) mi[i]=mi[i-1]*2;
	for (i=1;i<=m;i++) read(x),read(y),read(z),insert(x,y,z),insert(y,x,z);
	h.push(1);memset(dis,60,sizeof(dis));dis[1]=0;
	while (!h.empty())
	{
		int st=h.front();h.pop();
		for (k=q[st];k;k=f[k][2])
		{
			if (dis[st]+f[k][3]<dis[f[k][1]])
			{
				dis[f[k][1]]=dis[st]+f[k][3];
				h.push(f[k][1]);
			}
		}
	}
	dg(1);memset(vis,0,sizeof(vis));
	dfs(1);
	for (i=1;i<=17;i++)
		for (j=1;j<=n;j++)
			b[j][i]=b[b[j][i-1]][i-1];
	read(times);
	while (times--)
	{
		read(x),read(y),xx=x,yy=y,z=lca(x,y);
		if (co[x]==co[y]&&co[x])
		{
			s=abs(len[x]-len[y]);
			printf("%d\n",dis[xx]-dis[x]+dis[yy]-dis[y]+min(s,sum[co[x]]-s));
		} else printf("%d\n",dis[xx]+dis[yy]-2*dis[z]);
	}
	return 0;
}

主席树 JZOJ7050

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define ll long long
#define mo 998244353
#define N 100005
#define M 10000005
using namespace std;
int dep[N],f[N<<1][3],q[N],lson[M],rson[M],root[N],tree[M];
int pr[M>>3],bz[M],a[N],mn[M],c[N];
int ys[N][9],sum[N][9],len[N],id[N];
int b[N][18],mi[18];
struct node{
	int val,dep;
	friend bool operator <(node a,node b) {return a.dep<b.dep;}
};
set<node> g[M];
int dfn[N],size[N];
int i,j,k,m,n,o,p,l,s,t,x,y,tot,h,lastans,opt;
void read(int &x)
{
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
void insert(int x,int y) {f[++t][1]=y,f[t][2]=q[x],q[x]=t;}
void dg(int t,int fa)
{
	dep[t]=dep[fa]+1,dfn[t]=++tot,size[t]=1;
	for (int k=q[t];k;k=f[k][2])
	{
		if (f[k][1]==fa) continue;
		b[f[k][1]][0]=t;
		dg(f[k][1],t);
		size[t]+=size[f[k][1]];
	}
}
bool cmp(int a,int b) {return dep[a]<dep[b];}
int ksm(int x,int y)
{
	int ans=1;
	for (;y;y>>=1,x=1ll*x*x%mo)
		if (y&1) ans=1ll*ans*x%mo;
	return ans;
}
int getlca(int x,int y)
{
	if (dep[x]<dep[y]) swap(x,y);
	int k=dep[x]-dep[y];
	for (int i=17;i>=0;i--)
		if (k>=mi[i]) k-=mi[i],x=b[x][i];
	if (x==y) return x;
	for (int i=17;i>=0;i--)
		if (b[x][i]!=b[y][i]) x=b[x][i],y=b[y][i];
	return b[x][0];
}
void change(int &x,int l,int r,int pos,int mul)
{
	if (!x) x=++tot,tree[x]=1;
	if (l==r) {
		tree[x]=1ll*tree[x]*mul%mo;return;	
	}
	int mid=l+r>>1;
	if (pos<=mid) change(lson[x],l,mid,pos,mul);
	else change(rson[x],mid+1,r,pos,mul);
	tree[x]=1ll*tree[lson[x]]*tree[rson[x]]%mo;
}
int merge(int l,int r,int x,int y)
{
	if (!x||!y) return x+y;
	if (l==r) 
	{
		tree[x]=1ll*tree[x]*tree[y]%mo;
		return x;
	}
	else {
		int mid=l+r>>1;
		lson[x]=merge(l,mid,lson[x],lson[y]);
		rson[x]=merge(mid+1,r,rson[x],rson[y]);
		tree[x]=1ll*tree[lson[x]]*tree[rson[x]]%mo;
		return x;
	}
}
int query(int x,int l,int r,int st,int en)
{
	if (l>=st&&r<=en) return tree[x];
	else {
		int mid=l+r>>1;
		if (en<=mid) return query(lson[x],l,mid,st,en);
		else if (st>mid) return query(rson[x],mid+1,r,st,en);
		else return 1ll*query(lson[x],l,mid,st,mid)*query(rson[x],mid+1,r,mid+1,en)%mo;
	}
}
int main()
{
	freopen("half.in","r",stdin);
	freopen("half.out","w",stdout);
	read(opt),read(n);
	for (i=mi[0]=1;i<=17;i++) mi[i]=mi[i-1]*2%mo;
	for (i=1;i<=n;i++) read(a[i]),o=(a[i]>o?a[i]:o);
	for (i=2;i<=o;i++)
	{
		if (!bz[i]) pr[++pr[0]]=i,mn[i]=i;
		for (j=1;j<=pr[0]&&pr[j]*i<=o;j++)
		{
			bz[i*pr[j]]=1,mn[i*pr[j]]=pr[j];
			if (!(i%pr[j])) break;
		}
	}
	for (i=1;i<=n-1;i++) read(x),read(y),insert(x,y),insert(y,x);
	dg(1,0);
	for (i=1;i<=n;i++)
	{
		c[0]=0;
		if (a[i]==1) continue;
		for (k=a[i];k>1;k/=mn[k]) c[++c[0]]=mn[k];
		sort(c+1,c+c[0]+1);
		for (j=1;j<=c[0];j++)
		{
			if (c[j]!=ys[i][len[i]]) ys[i][++len[i]]=c[j],sum[i][len[i]]=1;
			else sum[i][len[i]]++;
		}
	} 
 	memset(bz,0,sizeof(bz));
	for (i=1;i<=n;i++) id[i]=i;
	sort(id+1,id+n+1,cmp);tot=0,j=1;
	tree[0]=1;
	for (i=1;i<=17;i++)
		for (j=1;j<=n;j++)
			b[j][i]=b[b[j][i-1]][i-1];
	for (i=j=1;i<=n;i++)
	{
		root[i]=++tot,tree[tot]=1;
		if (i==3)
		{
			int ddf=0;
		}
		while (j<=n&&dep[id[j]]<=i)
		{
			for (k=1;k<=len[id[j]];k++)
			{
				int mul=1,inv=ksm(ys[id[j]][k],mo-2);
				for (l=1;l<=sum[id[j]][k];l++)
				{
					mul*=ys[id[j]][k];
					g[mul].insert((node){id[j],dfn[id[j]]});
					change(root[i],1,n,dfn[id[j]],ys[id[j]][k]);
					set<node>::iterator st=g[mul].begin(),en=g[mul].end(),pos=g[mul].find((node){id[j],dfn[id[j]]});
					en--;
					int bz1=((*st).dep==(*pos).dep),bz2=((*en).dep==(*pos).dep);
					if (!bz1) st=pos,st--,change(root[i],1,n,dfn[getlca(id[j],(*st).val)],inv);
					if (!bz2) en=pos,en++,change(root[i],1,n,dfn[getlca(id[j],(*en).val)],inv);
					if (!bz1&&!bz2) change(root[i],1,n,dfn[getlca((*st).val,(*en).val)],ys[id[j]][k]);
				} 
			}
			j++;
		}
		if (i==2)
		{
			int gsdfg=0;
		}
		merge(1,n,root[i],root[i-1]);
	}
	read(m);
	for (i=1;i<=m;i++) 
	{
		read(x),read(y);
		x^=(opt*lastans),y^=(opt*lastans);
		printf("%d\n",lastans=query(root[min(dep[id[n]],dep[x]+y)],1,n,dfn[x],dfn[x]+size[x]-1));
	}
	return 0;
}

Loading…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值