1、Splay

(Tyvj1728)

#include <bits/stdc++.h>

using namespace std;
const int MAXN=1e5+,INF=<<;
int n,op,x,root,ch[MAXN][],sz[MAXN],cnt[MAXN],val[MAXN],f[MAXN],tot=; void pushup(int x)
{sz[x]=sz[ch[x][]]+sz[ch[x][]]+cnt[x];} void Rotate(int x)
{
int y=f[x],z=f[y],k=(x==ch[y][]);
ch[z][y==ch[z][]]=x;f[x]=z;
ch[y][k]=ch[x][k^];f[ch[x][k^]]=y;
ch[x][k^]=y;f[y]=x;
pushup(x);pushup(y);
} void Splay(int x,int up)
{
while(f[x]!=up)
{
int y=f[x],z=f[y];
if(z!=up) (ch[y][]==x)^(ch[z][]==y)?Rotate(x):Rotate(y);
Rotate(x);
}
if(!up) root=x;
} void Insert(int x)
{
int k=root,anc=;
while(k&&x!=val[k])
anc=k,k=ch[k][x>val[k]]; if(k) cnt[k]++;
else
{
k=++tot;
if(anc) ch[anc][x>val[anc]]=k;
ch[k][]=ch[k][]=;
val[k]=x;cnt[k]=;sz[k]=;f[k]=anc;
}
Splay(k,);
} void Find(int x)
{
int k=root;
if(!k) return;
while(ch[k][x>val[k]]&&x!=val[k])
k=ch[k][x>val[k]];
Splay(k,);
} int Next(int x,int flag)
{
Find(x);
int k=root;
if((val[k]<x&&!flag)||(val[k]>x&&flag)) return k; k=ch[k][flag];
while(ch[k][flag^]) k=ch[k][flag^]; return k;
} int Kth(int x)
{
int k=root;
if(sz[k]<x) return ;
while(true)
{
if(x>sz[ch[k][]]+cnt[k])
x-=sz[ch[k][]]+cnt[k],k=ch[k][];
else if(sz[ch[k][]]>=x)
k=ch[k][];
else return val[k];
}
} void Delete(int x)
{
int lst=Next(x,),nxt=Next(x,);
Splay(lst,);Splay(nxt,lst); if(cnt[ch[nxt][]]>)
cnt[ch[nxt][]]--,Splay(ch[nxt][],);
else ch[nxt][]=;
} int main()
{
scanf("%d",&n);
Insert(INF);Insert(-INF);//记得先插入边界
for(int i=;i<=n;i++)
{
scanf("%d%d",&op,&x);
if(op==) Insert(x);
else if(op==) Delete(x);
else if(op==) Find(x),printf("%d\n",sz[ch[root][]]);
else if(op==) printf("%d\n",Kth(x+));
else if(op==) printf("%d\n",val[Next(x,)]);
else if(op==) printf("%d\n",val[Next(x,)]);
}
return ;
}

Splay

Tip:由于采取求前驱后继来删除节点的方式,要先$insert(INF)$和$insert(-INF)$

2、Treap

(Tyvj1728)

#include <bits/stdc++.h>

using namespace std;
const int MAXN=;
const int INF=<<;
int cnt=,root,n,s[MAXN][],siz[MAXN],val[MAXN],pri[MAXN]; void update(int i)
{siz[i]=siz[s[i][]]+siz[s[i][]]+;} void spin(int &i,int f)
{
int v=s[i][f^];
s[i][f^]=s[v][f];s[v][f]=i;
update(i);update(i=v);
} void ins(int &i,int k)
{
if(!i){i=++cnt;siz[i]=;val[i]=k;pri[i]=rand();return;} siz[i]++;
if(val[i]>=k){ins(s[i][],k);if(pri[i]>pri[s[i][]]) spin(i,);}
else{ins(s[i][],k);if(pri[i]>pri[s[i][]]) spin(i,);}
} int pre(int i,int k)
{
if(!i) return -INF;
if(val[i]<k) return max(val[i],pre(s[i][],k));
else return pre(s[i][],k);
} int nxt(int i,int k)
{
if(!i) return INF;
if(val[i]>k) return min(val[i],nxt(s[i][],k));
else return nxt(s[i][],k);
} int find_key(int i,int k)
{
if(siz[s[i][]]==k-) return val[i];
if(siz[s[i][]]>=k) return find_key(s[i][],k);
return find_key(s[i][],k-siz[s[i][]]-);
} int find_rank(int i,int k)
{
if(!i) return ;
if(val[i]>=k) return find_rank(s[i][],k);
return siz[s[i][]]++find_rank(s[i][],k);
} void del(int &i,int k)
{
if(val[i]==k)
{
if(s[i][]*s[i][]==)
{
i=s[i][]+s[i][];
return;
}
if(pri[s[i][]]<pri[s[i][]]) spin(i,),del(s[i][],k);
else spin(i,),del(s[i][],k);
}
else if(val[i]>=k) del(s[i][],k);
else del(s[i][],k);
update(i);
} int main()
{
scanf("%d",&n);srand(time(NULL));
while(n--)
{
int op,x;scanf("%d%d",&op,&x);
if(op==) ins(root,x);
else if(op==) del(root,x);
else if(op==) printf("%d\n",find_rank(root,x));
else if(op==) printf("%d\n",find_key(root,x));
else if(op==) printf("%d\n",pre(root,x));
else printf("%d\n",nxt(root,x));
}
return ;
}

Treap

Tip:注意递归边界

3、计算几何模板

我现在发现了我在计算几何方面就是个sillycross

在这里总结一下基本模块吧,

(使用complex<double>模板类)

点乘:

double dot(point a,point b){return real(a*conj(b));}

叉乘:

double det(point a,point b){return imag(a*conj(b));}

判断点x是否在线段[L,R]上:

bool on_seg(point x,point L,point R){return det(L-x,R-x)==0 && dot(L-x,R-x)<=0;}

判断三点是否在一条直线 + L,R是否在x的两侧

判断两线段是否相交(非严格):

bool seg_cross(point a,point b,point c,point d)
{
double s1=det(c-a,b-a)*det(b-a,d-a);
double s2=det(a-c,d-c)*det(d-c,b-c);
if(s1<0 || s2<0) return false;
if(s1==0 && s2==0) return on_seg(c,a,b) || on_seg(d,a,b);
return true;
}

对于每个点判断另一线段的两点是否在其两端  +   对一条线段的端点恰在另一线段上的特殊处理

求点x关于线段[A,B]的对称点:

point sym(point x,point A,point B){return 2*dot(A,B)/dot(B,B)*B-A+x;}

将线段[x,A]延长一倍,求出线段[x,x']的向量,再行加减即可

4、FFT

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=3e6+;
struct Complex
{
db x,y;
Complex(db a=,db b=){x=a;y=b;}
Complex operator + (const Complex& rhs)
{return Complex(x+rhs.x,y+rhs.y);}
Complex operator - (const Complex& rhs)
{return Complex(x-rhs.x,y-rhs.y);}
Complex operator * (const Complex& rhs)
{return Complex(x*rhs.x-y*rhs.y,x*rhs.y+y*rhs.x);}
}a[MAXN],b[MAXN];
int n,m,lmt=,dgt,par[MAXN]; void FFT(Complex *a,int flag)
{
for(int i=;i<lmt;i++)
if(i<par[i]) swap(a[i],a[par[i]]); for(int len=;len<lmt;len<<=)
{
Complex unit(cos(M_PI/len),flag*sin(M_PI/len));
for(int st=;st<lmt;st+=(len<<))
{
Complex w(,);
for(int k=st;k<st+len;k++,w=w*unit)
{
Complex A=a[k],B=w*a[k+len];
a[k]=A+B;a[k+len]=A-B;
}
}
}
if(flag==-)
for(int i=;i<=n+m;i++)
a[i].x=floor(a[i].x/lmt+0.5);
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%lf",&a[i].x);
for(int i=;i<=m;i++) scanf("%lf",&b[i].x);
while(lmt<=n+m) lmt<<=,dgt++;
for(int i=;i<lmt;i++)
par[i]=(par[i>>]>>)|((i&)<<(dgt-)); FFT(a,);FFT(b,);
for(int i=;i<lmt;i++)
a[i]=a[i]*b[i];
FFT(a,-);
for(int i=;i<=n+m;i++)
printf("%d ",(int)a[i].x);
return ;
}

FFT

5、NTT

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=4e6+,MOD=;
ll n,m,a[MAXN],b[MAXN],dgt,lmt=,par[MAXN]; ll quick_pow(ll a,ll b)
{
ll ret=;
for(;b;b>>=,a=a*a%MOD)
if(b&) ret=ret*a%MOD;
return ret;
}
void FFT(ll *a,int flag)
{
for(int i=;i<lmt;i++)
if(i<par[i]) swap(a[i],a[par[i]]);
for(int len=;len<lmt;len<<=)
{
ll unit=quick_pow(,(MOD-)/(len<<));
if(flag==-) unit=quick_pow(unit,MOD-);
for(int st=;st<lmt;st+=(len<<))
{
ll w=;
for(int k=st;k<st+len;k++,w=w*unit%MOD)
{
ll A=a[k],B=w*a[k+len]%MOD;
a[k]=(A+B)%MOD;a[k+len]=(A-B+MOD)%MOD;
}
}
}
} int main()
{
scanf("%lld%lld",&n,&m);
for(int i=;i<=n;i++) scanf("%lld",&a[i]);
for(int i=;i<=m;i++) scanf("%lld",&b[i]);
while(lmt<=n+m) lmt<<=,dgt++;
for(int i=;i<lmt;i++)
par[i]=(par[i>>]>>)|((i&)<<(dgt-)); FFT(a,);FFT(b,);
for(int i=;i<lmt;i++)
(a[i]*=b[i])%=MOD;
FFT(a,-);
ll inv=quick_pow(lmt,MOD-);
for(int i=;i<=n+m;i++)
printf("%lld ",a[i]*inv%MOD);
return ;
}

NTT

6、MTT

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=4e5+;
ll p[]={,,};
int n,m,MOD,F[MAXN],G[MAXN],dgt,lmt=;
ll a[][MAXN],b[MAXN],res[MAXN],par[MAXN]; ll quickpow(ll a,ll b,ll MOD)
{
a%=MOD;ll ret=;
for(;b;b>>=,a=a*a%MOD)
if(b&) ret=ret*a%MOD;
return ret;
}
ll mul(ll a,ll b,ll MOD)
{
a=(a%MOD+MOD)%MOD;
b=(b%MOD+MOD)%MOD;ll ret=;
for(;b;b>>=,a=(a+a)%MOD)
if(b&) (ret+=a)%=MOD;
return ret;
}
ll inv(ll a,ll MOD)
{return quickpow(a,MOD-,MOD);}
void FFT(ll *a,int flag,ll MOD)
{
for(int i=;i<lmt;i++)
if(i<par[i]) swap(a[i],a[par[i]]);
for(int len=;len<lmt;len<<=)
{
ll unit=quickpow(,(MOD-)/(len<<),MOD);
if(flag==-) unit=inv(unit,MOD);
for(int st=;st<lmt;st+=(len<<))
{
ll w=;
for(int k=st;k<st+len;k++,w=w*unit%MOD)
{
ll A=a[k],B=w*a[k+len]%MOD;
a[k]=(A+B)%MOD;a[k+len]=(A-B+MOD)%MOD;
}
}
}
if(flag==-)
{
ll INV=inv(lmt,MOD);
for(int i=;i<lmt;i++)
a[i]=a[i]*INV%MOD;
}
}
void solve(ll *a,ll *b,ll MOD)
{
for(int i=;i<=n;i++) a[i]=F[i];
for(int i=;i<=m;i++) b[i]=G[i];
for(int i=m+;i<lmt;i++) b[i]=;
FFT(a,,MOD);FFT(b,,MOD);
for(int i=;i<lmt;i++) a[i]=a[i]*b[i]%MOD;
FFT(a,-,MOD);
} int main()
{
scanf("%d%d%d",&n,&m,&MOD);
for(int i=;i<=n;i++) scanf("%d",&F[i]);
for(int i=;i<=m;i++) scanf("%d",&G[i]);
while(lmt<=n+m) lmt<<=,dgt++;
for(int i=;i<lmt;i++) par[i]=(par[i>>]>>)|((i&)<<(dgt-)); for(int i=;i<;i++) solve(a[i],b,p[i]);
for(int i=;i<=n+m;i++)
{
ll M=p[]*p[];
ll A=(mul(a[][i]*p[],inv(p[],p[]),M)+
mul(a[][i]*p[],inv(p[],p[]),M))%M;
ll K=mul(a[][i]-A,inv(M,p[]),p[]);
res[i]=(mul(K,M,MOD)+A%MOD)%MOD;
}
for(int i=;i<=n+m;i++)
printf("%lld ",res[i]);
return ;
}

CRT写法

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e6+;
struct Complex
{
db x,y;
Complex(db a=,db b=){x=a;y=b;}
Complex operator +(const Complex& rhs)
{return Complex(x+rhs.x,y+rhs.y);}
Complex operator -(const Complex& rhs)
{return Complex(x-rhs.x,y-rhs.y);}
Complex operator *(const Complex& rhs)
{return Complex(x*rhs.x-y*rhs.y,x*rhs.y+y*rhs.x);}
}a[MAXN],b[MAXN],w[MAXN],t1[MAXN],t2[MAXN],t3[MAXN];
int n,m,MOD,lmt=,dgt,par[MAXN];ll x,res[MAXN]; void FFT(Complex *a,int flag)
{
for(int i=;i<lmt;i++)
if(i<par[i]) swap(a[i],a[par[i]]);
for(int len=;len<lmt;len<<=)
for(int st=;st<lmt;st+=(len<<))
{
int cur=;
for(int k=st;k<st+len;k++)
{
Complex A=a[k],B=w[cur]*a[k+len];
a[k]=A+B;a[k+len]=A-B;
//预处理的写法
cur=(cur+flag*lmt/(len<<)+lmt)&(lmt-);
}
}
if(flag==-)
for(int i=;i<lmt;i++)
a[i].x=floor(a[i].x/lmt+0.5);
}
void solve()
{
FFT(a,);FFT(b,);
for(int i=;i<lmt;i++)
{
Complex d1,d2,d3,d4;
int j=(lmt-i)&(lmt-);
d1=(a[i]+Complex(a[j].x,-a[j].y))*Complex(0.5,);
d2=(a[i]-Complex(a[j].x,-a[j].y))*Complex(,-0.5);
d3=(b[i]+Complex(b[j].x,-b[j].y))*Complex(0.5,);
d4=(b[i]-Complex(b[j].x,-b[j].y))*Complex(,-0.5);
//必须先用临时变量存,因为后面还要用
t1[i]=d1*d3;t2[i]=d1*d4+d2*d3;t3[i]=d2*d4;
}
for(int i=;i<lmt;i++)
//充分利用虚部空间(可看成逆过程)
b[i]=t2[i],a[i]=t1[i]+t3[i]*Complex(,);
FFT(a,-);FFT(b,-);
for(int i=;i<lmt;i++)
{
ll k1=(ll)a[i].x%MOD,k2=(ll)b[i].x%MOD;
ll k3=(ll)floor(a[i].y/lmt+0.5)%MOD;
res[i]=((k3<<)%MOD+(k2<<)%MOD+k1)%MOD;
}
} int main()
{
scanf("%d%d%d",&n,&m,&MOD);
for(int i=;i<=n;i++)
scanf("%lld",&x),a[i]=Complex(x&,x>>);
for(int i=;i<=m;i++)
scanf("%lld",&x),b[i]=Complex(x&,x>>);
while(lmt<=n+m) lmt<<=,dgt++;
for(int i=;i<lmt;i++)
par[i]=(par[i>>]>>)|((i&)<<(dgt-));
for(int i=;i<lmt;i++)
w[i]=Complex(cos(*M_PI*i/lmt),sin(*M_PI*i/lmt)); solve();
for(int i=;i<=n+m;i++)
printf("%lld ",res[i]);
return ;
}

拆系数4次DFT/IDFT

实测$myy$论文里拆系数优化至4次$DFT/IDFT$的方法比三模数$CRT$快7倍左右

7、SA

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
#define pb push_back
#define debug(x) cerr<<#x<<"="<<x<<endl
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e6+;
char s[MAXN];
int len,lmt,cnt[MAXN],sa[MAXN],x[MAXN],y[MAXN],cur; void solve()
{
for(int i=;i<=len;i++)
cnt[x[i]=s[i]]++;
for(int i=;i<=lmt;i++)
cnt[i]+=cnt[i-];
for(int i=len;i>=;i--)
sa[cnt[x[i]]--]=i; for(int k=;k<=len;k<<=,lmt=cur)
{
cur=;
for(int i=len-k+;i<=len;i++)
y[++cur]=i;
for(int i=;i<=len;i++)
if(sa[i]>k) y[++cur]=sa[i]-k; for(int i=;i<=lmt;i++) cnt[i]=;
for(int i=;i<=len;i++) cnt[x[i]]++;
for(int i=;i<=lmt;i++) cnt[i]+=cnt[i-];
//一定要按第二关键字从大往小枚举!
for(int i=len;i>=;i--)
sa[cnt[x[y[i]]]--]=y[i]; swap(x,y);cur=;x[sa[]]=;
for(int i=;i<=len;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-]]&&y[sa[i]+k]==y[sa[i-]+k])?cur:++cur;
if(cur==len) break;
}
} int main()
{
scanf("%s",s+);
len=strlen(s+);lmt=;
solve();
for(int i=;i<=len;i++)
printf("%d ",sa[i]);
return ;
}

SA

Template(Updating)的更多相关文章

  1. 论文笔记之:Learning to Track: Online Multi-Object Tracking by Decision Making

    Learning to Track: Online Multi-Object Tracking by Decision Making ICCV   2015 本文主要是研究多目标跟踪,而 online ...

  2. Go 1 Release Notes

    Go 1 Release Notes Introduction to Go 1 Changes to the language Append Close Composite literals Goro ...

  3. Quality in the Test Automation Review Process and Design Review Template

    About this document Prerequisite knowledge/experience: Software Testing, Test Automation Applicable ...

  4. XML Publisher Template Type - Microsoft Excel Patch

    XML Publisher Template Type - Microsoft Excel Patch Oracle XML Publisher > Templates > Create ...

  5. git commit template

    https://www.zhihu.com/question/27462267/answer/204658544 https://gist.github.com/adeekshith/cd4c95a0 ...

  6. 模板库 ~ Template library

    TOC 建议使用 Ctrl+F 搜索 . 目录 小工具 / C++ Tricks NOI Linux 1.0 快速读入 / 快速输出 简易小工具 无序映射器 简易调试器 文件 IO 位运算 Smart ...

  7. 为.NET Core项目定义Item Template

    作为这个星球上最强大的IDE,Visual Studio不仅仅提供了很多原生的特性,更重要的是它是一个可定制的IDE,比如自定义Project Template和Item Template就是一个非常 ...

  8. jQuery.template.js 简单使用

    之前看了一篇文章<我们为什么要尝试前后端分离>,深有同感,并有了下面的评论: 我最近也和前端同事在讨论这个问题,比如有时候前端写好页面给后端了,然后后端把这些页面拆分成很多的 views, ...

  9. 2000条你应知的WPF小姿势 基础篇<69-73 WPF Freeze机制和Template>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...

随机推荐

  1. javaScript书写规范

    命名规范. 常量名    全部大写并单词间用下划线分隔    如:CSS_BTN_CLOSE.TXT_LOADING对象的属性或方法名    小驼峰式(little camel-case)    如: ...

  2. C++ 之Boost 实用工具类及简单使用

    本文将介绍几个 Boost 实用工具类,包括 tuple.static_assert.pool.random 和 program_options等等.需要对标准 STL 具备一定的了解才能充分理解本文 ...

  3. MVVM模式的 数据绑定

    数据绑定要达到的效果 数据绑定要达到什么效果呢,就是在界面中绑定了数据源之后,数据在界面上的修改能反映到绑定源,同时绑定源的修改也能反映到界面上.从界面反映到绑定的数据源是很容易理解的,因为在绑定过程 ...

  4. C基础 旋转数组查找题目

    前言 - 引言 题目: 一类有序数组旋转查值问题. 例如: 有序数组 [ , , , , , , , , ] 旋转后为 [ , , , , , , , , ] 如何从中找出一个值索引, not fou ...

  5. 动态RNN和静态RNN区别

    调用static_rnn实际上是生成了rnn按时间序列展开之后的图.打开tensorboard你会看到sequence_length个rnn_cell stack在一起,只不过这些cell是share ...

  6. 签名DLL

    签名DLL 首先需要一个密钥文件,后缀为.snk 密钥文件使用sn.exe 创建: sn.exe /k MySingInKey.snk  sn.exe 工具的具体使用,可以通过 sn.exe /h 或 ...

  7. 下一代Android打包工具,100个渠道包只需要10秒钟 https://github.com/mcxiaoke

    https://github.com/mcxiaoke/packer-ng-plugin https://github.com/Meituan-Dianping/walle https://githu ...

  8. 分别使用docx4j,jacob将文字与图片插入word中书签位置

    项目中需要将一段文字,与人员的签名(图片)插入到上传的word中,上网查询了一下,有许多种方式可以向word中插入文字,发现docx4j与jacob都为比较常见的解决方案,于是就先使用的docx4j进 ...

  9. elasticsearch文档学习

    1.集群 节点(一个elasticsearch实体)  索引  主节点 :集群级别变更,新增或移除节点,索引:  主节点不参与文档级别搜索和变更. 分片(shard):一个完整的搜索引擎,lucene ...

  10. POJ 2955 Brackets(括号匹配一)

    题目链接:http://poj.org/problem?id=2955 题目大意:给你一串字符串,求最大的括号匹配数. 解题思路: 设dp[i][j]是[i,j]的最大括号匹配对数. 则得到状态转移方 ...