FFT(快速傅里叶变换)
void FFT(complex<double>*p,int n,int tt){ complex<double>aa,bb,t0,t1; int i,j,k,m; for(i=0;i<n;i++){ for(j=0,k=i,m=n-1;m>0;j=(j<<1)|(k&1),k>>=1,m>>=1);//可以写在外面,用rev[]代替j,效率更高 if(i<j)swap(p[i],p[j]); } for(m=1;m<n;m<<=1){ aa=exp(complex<double>(0,tt*pi/(double)(m))); for(i=0;i<n;i+=(m<<1)){ bb=1; for(j=0;j<m;j++){ t0=p[i+j]; t1=p[i+j+m]*bb; p[i+j]=t0+t1; p[i+j+m]=t0-t1; bb*=aa; } } } if(tt==-1) { for(int i=0; i<n; i++) p[i]/=n; } }
BSGS算法
(map)求a^x=b(mod p)(p为质数)
ll ksm(ll x,ll y){ ll ans=1; while(y){ if(y&1)ans=(ans*x)%P; y>>=1; x=(x*x)%P; } return ans; } ll bsgs(ll a,ll b,ll p){ if(b==1)return 0; ll m=ceil(sqrt(p)); ll k=1; q.clear(); ll cc=ksm(a,m); ll ss=b; q[ss]=0; for(int i=1;i<=m;i++){ ss=ss*a%p; q[ss]=i; } ll o=1; for(int i=1;i<=m;i++){ o=o*cc%p; if(q[o]){ return i*m-q[o]+js; } } return -1; }
(Hash表)
ll ksm(ll x,ll y){ ll ans=1; while(y){ if(y&1)ans=(ans*x)%P; y>>=1; x=(x*x)%P; } return ans; } struct hashmap{ static const int mod=999917,maxn=50005; int _end[maxn],_next[maxn],_last[mod],state[maxn],val[maxn]; int o,top; void clear(){ o=0; while(top){ _last[state[top--]]=0; } } void add(int x,int y){ _end[++o]=y; _next[o]=_last[x]; _last[x]=o; val[o]=0x3f3f3f3f; } bool count(int y){ int x=y%mod; for(int j=_last[x];j;j=_next[j]){ if(y==_end[j])return 1; } return 0; } int& operator[](int y){ int x=y%mod; for(int j=_last[x];j;j=_next[j]){ if(y==_end[j]){ return val[j]; } } add(x,y); state[++top]=x; return val[o]; } }; hashmap Hash; ll exbsgs(ll a,ll b,ll p){ if(b==1)return 0; ll k=1; ll cc; ll m=ceil(sqrt(p)); Hash.clear(); cc=ksm(a,m); ll ss=b; Hash[ss]=0; for(int i=1;i<=m;i++){ ss=ss*a%p; Hash[ss]=i; } for(int i=1;i<=m;i++){ k=k*cc%p; if(Hash.count(k)){ return i*m-Hash[k]; } } return -1; }
Catalan数
void cg(int k,int tt){ int cc=0; for(int i=100;i>=0;i--){ cc += a[k-1][i]*tt; a[k][i]=cc%BASE; cc/=BASE; } } void ch(int k,int tt){ int cc=0; for(int i=0;i<=100;i++){ cc=cc*BASE+a[k][i]; a[k][i]=cc/tt; cc%=tt; } } int main(){ memset(a,0,sizeof(a)); a[0][100] = 1; for(int i = 1;i <= 100;i++){ cg(i,4*i-2); ch(i,i+1); } int n; scanf("%d",&n); while(n!=-1){ int pos=-1; for(int i=0;i<=100;i++){ if(a[n][i]){ pos=i; break; } } printf("%d",a[n][pos]); for(int i=pos+1;i<=100;i++){ printf("%04d",a[n][i]); } printf(" "); scanf("%d",&n); } return 0; }
后缀自动机
ll push(ll x){ mx[++tot]=x; return tot; } struct node{ void init(){ memset(son,0,sizeof(son)); memset(pre,0,sizeof(pre)); last=tot=root=1; } void ins(ll t){ ll p=last,np=push(mx[p]+1); si[np]=tt[np]=1; while(p&&!son[p][t]){ son[p][t]=np; p=pre[p]; } if(!p)pre[np]=root; else{ ll q=son[p][t]; if(mx[q]==mx[p]+1)pre[np]=q; else{ ll nq=push(mx[p]+1); memcpy(son[nq],son[q],sizeof(son[q])); pre[nq]=pre[q]; pre[q]=pre[np]=nq; while(p&&son[p][t]==q){ son[p][t]=nq; p=pre[p]; } } } last=np; } }sam;
SAM的拓扑排序
ll push(ll x){ mx[++tot]=x; return tot; } struct node{ void init(){ memset(pre,0,sizeof(pre)); last=root=tot=1; } void ins(ll t){ ll p=last,np=push(mx[p]+1); v1[np]=1; while(p&&!son[p][t]){ son[p][t]=np; p=pre[p]; } if(!p){ pre[np]=root; ++dd[root]; } else{ ll q=son[p][t]; if(mx[q]==mx[p]+1){ pre[np]=q; ++dd[q]; } else{ ll nq=push(mx[p]+1); son[nq]=son[q]; pre[nq]=pre[q]; pre[q]=pre[np]=nq; dd[nq]+=2;/*****/ while(p&&son[p][t]==q){ son[p][t]=nq; p=pre[p]; } } } last=np; } void topsortr(){ queue<ll>Q; for(ll i=1;i<=tot;++i) { if(!dd[i])Q.push(i); } ll ans=0; while(Q.size()){ ll tt=Q.front(); Q.pop(); v1[pre[tt]]+=v1[tt]; --dd[pre[tt]]; if(!dd[pre[tt]])Q.push(pre[tt]); } } }sam;
树状数组(加减以及求答案操作)
void add(int x,int d){ if(!x)return; while(x<=N){ c[x]+=d; x+=lowbit(x); } } int gs(int x){ if(!x)return 0; int anss=0; while(x){ anss+=c[x]; x-=lowbit(x); } return anss; }
二逼平衡树(线段树套splay)
#include<stdio.h> #include<math.h> #include<algorithm> #include<iostream> #include<string.h> #define maxn 1000005 #define inf 0x3f3f3f3f using namespace std; int N,M; int v[maxn],fz[maxn],ch[maxn][2],si[maxn],cnt[maxn]; int root[maxn],pp[maxn]; int Pre,Suc; int tot; int maxx; void update(int x){ si[x]=si[ch[x][0]]+si[ch[x][1]]+cnt[x]; } void xz(int x,int &rt){ int y=fz[x],z=fz[y]; bool t=(ch[y][0]==x); if(z)ch[z][ch[z][1]==y]=x; else rt=x; fz[x]=z; fz[y]=x; fz[ch[x][t]]=y; ch[y][t^1]=ch[x][t]; ch[x][t]=y; update(y); update(x); } void splay(int x,int &rt){ while(x!=rt){ int y=fz[x],z=fz[y]; if(y==rt){ xz(x,rt); return; } if((ch[y][0]==x)^(ch[z][0]==y))xz(x,rt); else xz(y,rt); xz(x,rt); } } void ins(int &p,int x,int fa,int id){ if(!p){ p=++tot; v[p]=x; fz[p]=fa; cnt[p]=si[p]=1; splay(p,root[id]); return; } if(v[p]==x){ cnt[p]++; si[p]++; splay(p,root[id]); } else{ if(x<v[p])ins(ch[p][0],x,p,id); else ins(ch[p][1],x,p,id); } } int find(int p,int x){ if(v[p]==x)return p; if(x<v[p])return find(ch[p][0],x); else return find(ch[p][1],x); } void del(int x,int id){ int p=find(root[id],x); splay(p,root[id]); if(cnt[p]>1){ cnt[p]--; si[p]--; return; } if((!ch[p][0])||(!ch[p][1])){ root[id]=ch[p][0]+ch[p][1]; fz[root[id]]=0; return; } int pre=ch[p][0],suc=ch[p][1]; while(ch[pre][1])pre=ch[pre][1]; while(ch[suc][0])suc=ch[suc][0]; splay(pre,root[id]); splay(suc,ch[root[id]][1]); ch[suc][0]=0; update(suc); update(pre); } void inss(int p,int l,int r,int id,int k){ ins(root[p],k,0,p); if(l==r)return; int mid=l+r>>1; if(id<=mid)inss(p<<1,l,mid,id,k); else inss(p<<1|1,mid+1,r,id,k); } int cx1(int p,int x){ if(!p)return 0; if(x<v[p])return cx1(ch[p][0],x); else{ if(x==v[p])return si[ch[p][0]]; else return si[ch[p][0]]+cnt[p]+cx1(ch[p][1],x); } } int sl1(int p,int l,int r,int L,int R,int x){ if(L<=l&&r<=R)return cx1(root[p],x); int mid=l+r>>1; int anss=0; if(L<=mid)anss+=sl1(p<<1,l,mid,L,R,x); if(mid+1<=R)anss+=sl1(p<<1|1,mid+1,r,L,R,x); return anss; } int sl2(int L,int R,int k){ int l=1,r=maxx; int ans=0; while(l<=r){ int mid=l+r>>1; if(sl1(1,1,N,L,R,mid)>=k)r=mid-1; else{ l=mid+1; ans=mid; } } return ans; } void sl3(int p,int l,int r,int pos,int x){ if(l==r){ v[root[p]]=x; return; } del(pp[pos],p); ins(root[p],x,0,p); int mid=l+r>>1; if(pos<=mid)sl3(p<<1,l,mid,pos,x); else sl3(p<<1|1,mid+1,r,pos,x); } void cx4(int p,int x){ if(v[p]<x){ Pre=max(Pre,v[p]); if(ch[p][1])cx4(ch[p][1],x); } else{ if(ch[p][0])cx4(ch[p][0],x); } } void sl4(int p,int l,int r,int L,int R,int x){ if(L<=l&&r<=R){ cx4(root[p],x); return; } int mid=l+r>>1; if(L<=mid)sl4(p<<1,l,mid,L,R,x); if(mid+1<=R)sl4(p<<1|1,mid+1,r,L,R,x); } void cx5(int p,int x){ if(v[p]>x){ Suc=min(Suc,v[p]); if(ch[p][0])cx5(ch[p][0],x); } else{ if(ch[p][1])cx5(ch[p][1],x); } } void sl5(int p,int l,int r,int L,int R,int x){ if(L<=l&&r<=R){ cx5(root[p],x); return; } int mid=l+r>>1; if(L<=mid)sl5(p<<1,l,mid,L,R,x); if(mid+1<=R)sl5(p<<1|1,mid+1,r,L,R,x); } int main(){ scanf("%d%d",&N,&M); for(int i=1;i<=N;++i){ scanf("%d",&pp[i]); inss(1,1,N,i,pp[i]); maxx=max(maxx,pp[i]); } int ty; int pos,l,r,k; while(M--){ scanf("%d",&ty); if(ty==1){ scanf("%d%d%d",&l,&r,&k); printf("%d ",sl1(1,1,N,l,r,k)+1); continue; } if(ty==2){ scanf("%d%d%d",&l,&r,&k); printf("%d ",sl2(l,r,k)); continue; } if(ty==3){ scanf("%d%d",&pos,&k); sl3(1,1,N,pos,k); maxx=max(maxx,k); pp[pos]=k; continue; } if(ty==4){ scanf("%d%d%d",&l,&r,&k); Pre=-inf; sl4(1,1,N,l,r,k); printf("%d ",Pre); continue; } if(ty==5){ scanf("%d%d%d",&l,&r,&k); Suc=inf; sl5(1,1,N,l,r,k); printf("%d ",Suc); } } return 0; }
线性基(合并)
struct xxj{ ll v[65]; void add(ll x){ for(int i=61;i>=0;--i){ if(x&(1ll<<i)){ if(!v[i]){ v[i]=x; break; } x^=v[i]; } } } ll cx(){ ll anss=0; for(int i=61;i>=0;--i){ anss=max(anss,anss^v[i]); } return anss; } }g[20005][20]; xxj oh_yeah(xxj a,xxj b){ xxj xxx=a; for(int i=61;i>=0;--i){ if(b.v[i]){ xxx.add(b.v[i]); } } return xxx; }
伪四维偏序(三维偏序)【[Ahoi2008]Rectangle 矩形藏宝地】
#include<stdio.h> #include<iostream> #include<math.h> #include<string.h> #include<algorithm> #define ll long long #define maxn 200005 #define lowbit(x) (x&(-x)) using namespace std; int N; int ans[maxn<<1]; struct node{ int x1,y1,x2,y2; int id; bool fg; }p[maxn<<1],pp[maxn<<1]; int lsh[maxn<<1]; bool cmp(node a,node b){ return a.x1<b.x1; } int c[maxn<<1]; int maxx; void add(int x,int d){ while(x<=maxx){ c[x]=max(c[x],d); x+=lowbit(x); } } void xxx(int x){ while(x<=maxx){ c[x]=0; x+=lowbit(x); } } int gs(int x){ int anss=0; while(x){ anss=max(anss,c[x]); x-=lowbit(x); } return anss; } void solve(int l,int r){ if(l==r)return; int mid=l+r>>1; solve(l,mid); solve(mid+1,r); int i=l,j,tt=l; for(j=mid+1;j<=r;++j){ while(p[i].y1<=p[j].y1&&i<=mid){ add(maxx-p[i].x2,p[i].y2); pp[tt++]=p[i]; i++; } pp[tt++]=p[j]; if(gs(maxx-p[j].x2)>p[j].y2){ ans[p[j].id]=1; } } while(i<=mid){ pp[tt++]=p[i++]; } for(i=l;i<=mid;++i){ xxx(maxx-p[i].x2); } for(int i=l;i<=r;++i){ p[i]=pp[i]; } } int main(){ scanf("%d",&N); for(int i=1;i<=N;++i){ scanf("%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2); lsh[i]=p[i].x2; p[i].id=i; } maxx=N+1; sort(lsh+1,lsh+1+N); for(int i=1;i<=N;++i){ p[i].x2=lower_bound(lsh+1,lsh+1+N,p[i].x2)-lsh; } sort(p+1,p+1+N,cmp); solve(1,N); int anss=0; for(int i=1;i<=N;++i){ if(ans[i])anss++; } printf("%d",anss); return 0; }