一些模板(后缀数组+虚树+辛普森积分+凸包+博弈论搜索+矩阵求逆+高斯消元+半平面交+LCT基本操作)
2018-02-24 09:37
344 查看
这里贴一些不太熟的板子,方便以后复习,有空再来加点注释。
1、后缀数组(感觉我的板子还是挺优美的 (⊙∀⊙)(⊙∀⊙) 嗯)
2、建虚树(加了点注释,加“?”的地方不确定对不对(⊙o⊙),看到的dalao们可以顺便解答下嘛~(虽然BLOG万年没更新,大概不会有人看了┭┮﹏┭┮……))
3、辛普森积分
4、O(n log n)求凸包
5、博弈论搜索
6、矩阵求逆(这份板子是模意义下的矩阵求逆,还附了矩阵hash)
7、看到一种更短的高斯消元
8、半平面交(zzy排序增量算法优化 O(n log n))
9、Link-Cut Tree基本操作
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; } }
相关文章推荐
- c++模板实现二叉树,线索化,线索化遍历,非递归遍历及一些基本操作
- SQL语句添加、修改、删除字段及一些表与字段的基本操作
- Linux内核中的一些基本数据结构操作
- 控件的一些基本操作,设置颜色,自动连接,插入图片,padding,ellipsize。
- ZOJ Monthly, March 2014,3765 Lights (Splay 基本操作,并维护区间上的信息 * 模板)
- MYSQL的一些基本操作指令
- maven一些基本操作
- oracle 一些基本操作语句
- MySQL的一些基本操作
- EF CodeFirst关于数据库的一些基本操作
- C#中对XML文件的一些基本操作
- Jquery中对radiobutton、checkbox、dropdownlist等一些基本操作总结
- C的一些基本指针操作
- Jquery 表单取值赋值的一些基本操作
- 对MySQL日志操作的一些基本命令总结
- IOS 之 NSURL的一些基本操作
- 【Linux基础学习之一】关于Linux的一些基本操作(linux登陆、口令文件、多终端登陆)
- 操作Json和Json数组的一些基本方法
- django模板中做一些基本运算
- MySQL 一些基本操作