您的位置:首页 > 其它

一些模板(后缀数组+虚树+辛普森积分+凸包+博弈论搜索+矩阵求逆+高斯消元+半平面交+LCT基本操作)

2018-02-24 09:37 344 查看
这里贴一些不太熟的板子,方便以后复习,有空再来加点注释。

1、后缀数组(感觉我的板子还是挺优美的 (⊙∀⊙)(⊙∀⊙) 嗯)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 200005
int SA
,rank
,height
,tax
,tp
,a
,n,m;
char ch
,ALL
,st
;
void Rsort()
{
for (int i=0;i<=m;i++) tax[i]=0;
for (int i=1;i<=n;i++) tax[rank[tp[i]]]++;
for (int i=1;i<=m;i++) tax[i]+=tax[i-1];
for (int i=n;i>=1;i--) SA[tax[rank[tp[i]]]--]=tp[i];
/* an di yi guan jian zi pai xu ,
di er guan jian zi pai ming kao hou de hou zhui
you xian bei fang dao hou mian*/
}
int cmp(int *f,int x,int y,int w)
{
return f[x]==f[y]&&f[x+w]==f[y+w];
}

void Suffix()
{
for (int i=1;i<=n;i++) rank[i]=a[i],tp[i]=i;
m=127; Rsort();
for (int w=1,p=1,i;p<n;w+=w,m=p)
{
for (p=0,i=n-w+1;i<=n;i++) tp[++p]=i;
for (i=1;i<=n;i++) if (SA[i]>w) tp[++p]=SA[i]-w;
Rsort(),swap(rank,tp),rank[SA[1]]=p=1;
for (i=2;i<=n;i++)
rank[SA[i]]=cmp(tp,SA[i],SA[i-1],w)?p:++p;
}
int j,k=0;
for (int i=1;i<=n;height[rank[i++]]=k)
for (k=k?k-1:k,j=SA[rank[i]-1];a[i+k]==a[j+k];++k);
}
int main()
{
scanf("%s",st);
n=strlen(st);
for (int i=0;i<n;i++) a[i+1]=st[i];
Suffix();
for (int i=1;i<=n;i++) printf("%d ",SA[i]); printf("\n");
for (int i=1;i<=n;i++) printf("%d ",height[i]);
return 0;
}


2、建虚树(加了点注释,加“?”的地方不确定对不对(⊙o⊙),看到的dalao们可以顺便解答下嘛~(虽然BLOG万年没更新,大概不会有人看了┭┮﹏┭┮……))

void build_vtree()
{
sort(h+1,h+m+1,cmp);  //按dfn排序
tot=0; top=0; sta[++top]=1; head[1]=0; //1是虚树的根?
for (int i=1+(h[1]==1);i<=m;i++)
{
int lca=LCA(h[i],sta[top]); //栈顶和新加入节点的lca
if (lca!=sta[top])
{
while (dfn[sta[top-1]]>dfn[lca]) //要开辟一条更右的树杈?
{
push(sta[top],sta[top-1]); //原先维护的最右链连起来
top--;
}
if (dfn[sta[top-1]]<dfn[lca]) //lca需要加进虚树中
{
head[lca]=0;
push(sta[top],lca);
sta[top]=lca;
}
else push(sta[top--],lca);
}
head[h[i]]=0;
sta[++top]=h[i];
}
for (int i=1;i<top;i++) push(sta[i],sta[i+1]);
}


3、辛普森积分

DB f(DB X) //求高度
{
DB h=0;
/*......*/
return h;
}
DB simpson(DB a,DB b,DB fa,DB fb,DB fm)
{
return (b-a)/6*(fa+4*fm+fb);
}
DB area(DB l,DB fl,DB m,DB fm,DB r,DB fr,DB pre)
{
DB ls=(l+m)/2,rs=(m+r)/2,fls=f(ls),frs=f(rs);
DB la=simpson(l,m,fl,fm,fls),ra=simpson(m,r,fm,fr,frs);
if (fabs(la+ra-pre)<eps) return pre;
return area(l,fl,ls,fls,m,fm,la)+area(m,fm,rs,frs,r,fr,ra);
}


4、O(n log n)求凸包

#define sqr(x) ((x)*(x))
struct point{
double x,y;
point (double _x=0,double _y=0) { x=_x; y=_y; }
}p[1005],sta[1005];
double dis(point a,point b) { return sqr(a.x-b.x)+sqr(a.y-b.y); }
point operator - (point a,point b) { return point(a.x-b.x,a.y-b.y); }
double operator *(point a,point b) { return a.x*b.y-a.y*b.x; }
bool operator < (point a,point b)
{
double t=(a-p[1])*(b-p[1]);
return (t>0)||(t==0&&dis(p[1],a)<dis(p[1],b));
}
int convex_hull() //返回凸包上点的个数
{
int k=1,top=0;
for (int i=2;i<=n;i++)  //找最左下的点
if ((p[i].y<p[k].y)||(p[i].y==p[k].y&&p[i].x<p[k].x)) k=i;
swap(p[k],p[1]);
sort(p+2,p+n+1);  //按极角排序
sta[++top]=p[1]; sta[++top]=p[2];
for (int i=3;i<=n;i++)
{
while (top>1&&(sta[top]-sta[top-1])*(p[i]-sta[top-1])<=0)
top--;
sta[++top]=p[i];
}
sta[top+1]=p[1];
return top;
}


5、博弈论搜索

int dfs(int now)
{
if (SG[now]!=-1) return SG[now];
bool used[1005]; memset(used,false,sizeof(used));
for (int i=head[now];i;i=e[i].ne) used[dfs(e[i].to)]=true;
for (int i=0;;i++) if(!used[i]) { SG[now]=i; break; }
return SG[now];
}


6、矩阵求逆(这份板子是模意义下的矩阵求逆,还附了矩阵hash)

struct Matrix{
int a[75][75];
Matrix() { memset(a,0,sizeof(a)); }
inline void readM()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a[i][j]=read();
}
inline ull hash()   // +变成^
{
ull s=1,ret=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
ret^=(s*a[i][j]),s*=seed;
return ret;
}
inline Matrix get_inv()     //需要求逆元的矩阵右边拼一个单位矩阵之后高斯消元,右边得到的就是逆矩阵
{
static int b[75][150];
memset(b,0,sizeof(b));
for (int i=1;i<=n;i++)
{
b[i][n+i]=1;
for (int j=1;j<=n;j++)
b[i][j]=a[i][j];
}
for (int i=1;i<=n;i++)
{
for (int j=i+1;j<=n*2;j++)
(b[i][j]*=inv[b[i][i]])%=p;
b[i][i]=1;
for (int j=i+1;j<=n;j++)
for (int t=b[j][i],k=i;k<=n*2;k++)
b[j][k]=((b[j][k]-t*b[i][k])%p+p)%p;
}
for (int i=n;i>=1;i--)
for (int j=i+1;j<=n;j++)
for (int t=b[i][j],k=j;k<=2*n;k++)
b[i][k]=((b[i][k]-t*b[j][k])%p+p)%p;
Matrix ret;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
ret.a[i][j]=b[i][j+n];
return ret;
}
inline Matrix operator * (const Matrix &b) const
{
Matrix ret;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
for (int k=1;k<=n;k++)
ret.a[i][j]=(ret.a[i][j]+a[i][k]*b.a[k][j])%p;
return ret;
}
inline void operator *= (const Matrix b)
{
Matrix tmp=*this;
*this=tmp*b;
}
}


7、看到一种更短的高斯消元

void gauss()
{
double w;
for (int i=1;i<=siz;i++)
{
for (int j=i+1;j<=siz;j++)
{
w=-f[j][i]/f[i][i];
for (int k=1;k<=siz+1;k++)
f[j][k]+=w*f[i][k];
}
for (int j=i-1;j>=1;j--)
{
w=-f[j][i]/f[i][i];
for (int k=1;k<=siz+1;k++)
f[j][k]+=w*f[i][k];
}
}
for (int j=1;j<=siz;j++) f[j][siz+1]/=f[j][j];
}


8、半平面交(zzy排序增量算法优化 O(n log n))

#define N 505
typedef double db;
struct P{
db x,y;
P(db _x=0.0,db _y=0.0) { x=_x; y=_y; }
P operator + (const P a) const { return P(x+a.x,y+a.y); }
P operator - (const P a) const { return P(x-a.x,y-a.y); }
P operator * (const db k) const { return P(x*k,y*k); }
db operator * (const P a) const { return x*a.y-y*a.x; }
db operator / (const P a) const { return x*a.x+y*a.y; }
}a
;
struct L{
P x,y,v; db ang;
L(){}
L(P _x,P _y,P _v) { x=_x; y=_y; v=_v; ang=atan2(v.y,v.x); }
bool operator < (const L a) const { return ang<a.ang||ang==a.ang&&v*(a.y-x)>0; }
friend P inter(L a,L b)
{
P nw=b.x-a.x; db t=(nw*a.v)/(a.v*b.v);
return b.x+b.v*t;
}
friend bool jud(P a,L b) { return b.v*(a-b.x)<0; }
// 这里默认半平面为直线方向向量的逆时针一侧,jud为true表示点不在半平面内
}l
,q
;
int HPO(int cnt)
{
int tot=0;
sort(l+1,l+cnt+1);
for (int i=1;i<=cnt;i++)
{
if (l[i].ang!=l[i-1].ang) ++tot;
l[tot]=l[i];
}
cnt=tot; tot=0;
int tou=1,wei=2; q[1]=l[1]; q[2]=l[2];
for (int i=3;i<=cnt;i++)
{
while (tou<wei&&jud(inter(q[wei-1],q[wei]),l[i])) wei--;
while (tou<wei&&jud(inter(q[tou+1],q[tou]),l[i])) tou++;
q[++wei]=l[i];
}
while (tou<wei&&jud(inter(q[wei-1],q[wei]),q[tou])) wei--;
while (tou<wei&&jud(inter(q[tou+1],q[tou]),q[wei])) tou++;
q[wei+1]=q[tou];
for (int i=tou;i<=wei;i++) a[++tot]=inter(q[i],q[i+1]);
return tot;
}


9、Link-Cut Tree基本操作

#define N 300005
struct node{
int ch[2];
}T
;
int fa
;
int pd(int x)
{
if (x==T[fa[x]].ch[0]) return 0;
if (x==T[fa[x]].ch[1]) return 1; return -1;
}
void update(int x)
{
int ls=T[x].ch[0],rs=T[x].ch[1];
if (!ls&&!rs)
{
/* ······ */
return;
}
if (ls&&rs)
{
/* ······ */
}
else
{
if (ls)
{
/* ······ */
}
else
{
/* ······ */
}
}
}
void split(int x)
{
int y=T[x].ch[1];
/* ······ */
T[x].ch[1]=0; update(x);
}
void merge(int x,int y)
{
/* ······ */
T[x].ch[1]=y; update(x);
}
void rotate(int x)
{
int y=fa[x],z=fa[y],tx=pd(x),ty=pd(y);
if (~ty) T[z].ch[ty]=x; fa[x]=z;
if (T[x].ch[tx^1]) fa[T[x].ch[tx^1]]=y; T[y].ch[tx]=T[x].ch[tx^1];
T[x].ch[tx^1]=y; fa[y]=x;
update(y); update(x); if (~ty) update(z);
}
void splay(int x)
{
while (~pd(x))
{
if (~pd(fa[x]))
{
if (pd(fa[x])==pd(x)) rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
}
void access(int x)
{
splay(x);
if (T[x].ch[1]) split(x);
while (fa[x])
{
int y=fa[x]; splay(y);
if (T[y].ch[1]) split(y);
merge(y,x); update(x); x=y;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: