ACM模板.docx
- 文档编号:25046744
- 上传时间:2023-06-04
- 格式:DOCX
- 页数:31
- 大小:20.87KB
ACM模板.docx
《ACM模板.docx》由会员分享,可在线阅读,更多相关《ACM模板.docx(31页珍藏版)》请在冰豆网上搜索。
ACM模板
目录
1、数据结构
1.树链剖分(点权维护).................................................................................................................2
2.树链剖分(边权维护最值).........................................................................................................5
3.划分树.....................................................................................................................................10
4.一维RMQ..............................................................................................................................11
5.二维RMQ..............................................................................................................................12
2、字符串
1.AC自动机..............................................................................................................................13
2.哈希.........................................................................................................................................14
3、数学
1.高斯消元.................................................................................................................................15
2.扩展欧几里得求逆元.............................................................................................................16
3.卢卡斯定理.............................................................................................................................16
4、图论
1.LCA.........................................................................................................................................17
2.Tarjan强连通分量...............................................................................................................18
5、DP
1.背包..........................................................................................................................................19
一、数据结构
1.树链剖分(点权维护)
/**
树链剖分(点权维护)
树链剖分+树状数组维护路径上的点/边
HDOJ3966
*/
constintN=50010<<2;
structEdge
{
intto,next;
}edge[N<<2];
inthead[N],tot;
voidaddedge(intu,intv)
{
edge[tot]=(Edge){v,head[u]};
head[u]=tot++;
}
voidinit_edge()
{
memset(head,-1,sizeofhead);
tot=0;
}
///fa父节点dep深度num孩子数son重儿子
///top[u]它所在重链顶端节点p[u]在数据结构中位置rp--p的反
intfa[N],dep[N],top[N],num[N];
intson[N],p[N];
intpos;
voidinit()
{
init_edge();
pos=1;
memset(son,-1,sizeofson);
}
voiddfs(intu,intpre=-1,intd=0)
{
dep[u]=d;
fa[u]=pre;
num[u]=1;
for(inti=head[u];~i;i=edge[i].next)
{
intv=edge[i].to;
if(v==pre)continue;
dfs(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[son[u]] son[u]=v; } } voidgetpos(intu,intto=1) { top[u]=to; p[u]=pos++; if(~son[u])getpos(son[u],to); for(inti=head[u];~i;i=edge[i].next) { intv=edge[i].to; if(v-son[u]&&v-fa[u]) getpos(v,v); } } inlineintread(int&a) { charch=0; while(! isdigit(ch)&&~ch)ch=getchar(); a=0; while(isdigit(ch)&&~ch)a=a*10+ch-'0',ch=getchar(); return~ch? 0: -1; } intn,m,Q; /******BitIndexTree************/ inttree[N<<2]; inta[N]; intb[N]; inlineintlow(intx){returnx&-x;} voidadd(inti,intx) { for(;i<=n;i+=low(i))tree[i]+=x; } intsum(intp) { intres=0; for(inti=p;i>0;i-=low(i))res+=tree[i]; returnres; } /**********EndTree**********/ inlineintChange(intu,intv,intval) { intf1=top[u],f2=top[v]; inttmp=0; while(f1-f2) { if(dep[f1] { swap(f1,f2); swap(u,v); } add(p[f1],val); add(p[u]+1,-val); u=fa[f1]; f1=top[u]; } if(dep[u]>dep[v])swap(u,v); add(p[u],val); add(p[v]+1,-val); } intmain() { while(scanf("%d%d%d",&n,&m,&Q)==3) { init(); for(inti=1;i<=n;i++)read(a[i]); for(inti=0;i { intu,v; read(u);read(v); addedge(u,v); addedge(v,u); } dfs (1); getpos(1,1); memset(tree,0,sizeoftree); for(inti=1;i<=n;i++) { add(p[i],a[i]); add(p[i]+1,-a[i]); } while(Q--) { charop[22];scanf("%s",op); intu,v,val; if(op[0]=='I'||op[0]=='D') { read(u);read(v);read(val); if(op[0]=='D')val=-val; Change(u,v,val); } elseif(op[0]=='Q') { read(u); printf("%d\n",sum(p[u])); } } } return0; } 2.树链剖分(边权维护最值) /** 树链剖分(边权维护最值) 树链剖分+线段树 维护两点建路径上的边权最大值。 。 。 SPOJQTREE */ constintN=100100; #defineprt(k)cout<<#k"="< structEdge { intto,next; }e[N<<2]; inthead[N],Size; voidinit_edge() { memset(head,-1,sizeofhead); Size=0; } voidaddedge(intu,intv) { e[Size]=(Edge){v,head[u]}; head[u]=Size++; } intsiz[N],dep[N],fa[N],top[N],son[N],p[N]; ///fa父节点dep深度num孩子数son重儿子 ///top[u]它所在重链顶端节点p[u]他与父亲连边在数据结构中位置rpp的反 intn; voiddfs1(intu,intpre,intd) { siz[u]=1; fa[u]=pre; dep[u]=d; for(inti=head[u];~i;i=e[i].next) { intv=e[i].to; if(v==pre)continue; dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[son[u]] son[u]=v; } } intpos; voidgetPOS(intu,intto) { top[u]=to; p[u]=pos++; if(~son[u])getPOS(son[u],to); for(inti=head[u];~i;i=e[i].next) { intv=e[i].to; if(v-fa[u]&&v-son[u]) getPOS(v,v); } } voidinit() { memset(son,-1,sizeofson); init_edge(); pos=0; } /***********Tree*************/ inttree[N<<2]; #definelso*2 #definerso*2+1 #definelsonl,m,ls #definersonm+1,r,rs voidbuild(intl,intr,into) { tree[o]=0; if(l==r)return; intm=(l+r)/2; build(lson); build(rson); } voidpushup(into) { tree[o]=max(tree[ls],tree[rs]); } voidupdate(intpos,intval,intl=1,intr=n,into=1) { if(l==r) { if(l==pos)tree[o]=val; return; } intm=(l+r)/2; if(pos<=m)update(pos,val,lson); elseupdate(pos,val,rson); pushup(o); } intquery(intL,intR,intl,intr,into) { if(L<=l&&r<=R)returntree[o]; intm=(l+r)/2; intres=0; if(L<=m)res=max(res,query(L,R,lson)); if(m returnres; } inlineintquery(intL,intR) { //if(L>R)swap(L,R);if(L<1)L=1; returnquery(L,R,1,n,1); } /*********EndTree*************/ inlineintfind(intu,intv) { intf1=top[u],f2=top[v],tmp=0; while(f1-f2) { if(dep[f1] swap(f1,f2),swap(u,v); tmp=max(tmp,query(p[f1],p[u])); u=fa[f1];f1=top[u]; } if(u==v)returntmp; if(dep[u]>dep[v])swap(u,v); returnmax(tmp,query(p[son[u]],p[v])); } intedge[N][3]; inlinevoidread(int&a) { charc=0; while(! isdigit(c))c=getchar(); a=0; while(isdigit(c))a=a*10+c-'0',c=getchar(); } voidshow(intl,intr,into) { printf("[%d,%d]: tree[%d]=%d\n",l,r,o,tree[o]); if(l==r)return; intm=(l+r)/2; show(lson); show(rson); if(o==1)putchar(10); } intmain() { intT;scanf("%d",&T); while(T--) { scanf("%d",&n);n--; init(); for(inti=1;i<=n;i++){ inta,b,c; read(a);read(b);read(c); //scanf("%d%d%d",&a,&b,&c); edge[i][0]=a,edge[i][1]=b,edge[i][2]=c; addedge(a,b); addedge(b,a); } dfs1(1,1,0); getPOS(1,1); build(1,n,1); for(inti=1;i<=n;i++) { if(dep[edge[i][0]]>dep[edge[i][1]]) swap(edge[i][0],edge[i][1]); update(p[edge[i][1]],edge[i][2]); } charop[11]; while(scanf("%s",op)==1) { if(op[0]=='Q') { inta,b; //scanf("%d%d",&a,&b); read(a);read(b); //show(1,n,1); printf("%d\n",find(a,b)); } elseif(op[0]=='C') { inta,b; scanf("%d%d",&a,&b); update(p[edge[a][1]],b,1,n,1); } elseif(op[0]=='D') { putchar(10); break; } } } return0; } 3.划分树 /* 静态区间第K大的简单方法 */ constintmaxn=100100; inttree[20][maxn];///第i层的排列情况 intsorted[maxn];///排好序的数组 inttoleft[20][maxn];///第i层从1.到..j移动到左边的数的个数 voidbuild(intl,intr,intdep) { if(l==r)return; intmid=(l+r)/2; intsame=mid-l+1;///与mid相同的但要移动到左边的数的个数 for(inti=l;i<=r;i++) if(tree[dep][i] intlpos=l,rpos=mid+1; for(inti=l;i<=r;i++) { if(tree[dep][i] tree[dep+1][lpos++]=tree[dep][i]; elseif(tree[dep][i]==sorted[mid]&&same>0) { tree[dep+1][lpos++]=tree[dep][i]; same--; } elsetree[dep+1][rpos++]=tree[dep][i]; toleft[dep][i]=toleft[dep][l-1]+lpos-l; } build(l,mid,dep+1); build(mid+1,r,dep+1); } intquery(intL,intR,intl,intr,intdep,intk) { if(l==r)returntree[dep][l]; intmid=(L+R)/2; intcnt=toleft[dep][r]-toleft[dep][l-1]; if(cnt>=k) { intnewl=L+toleft[dep][l-1]-toleft[dep][L-1]; intnewr=newl+cnt-1; returnquery(L,mid,newl,newr,dep+1,k); } else { intnewr=r+toleft[dep][R]-toleft[dep][r]; intnewl=newr-(r-l-cnt); returnquery(mid+1,R,newl,newr,dep+1,k-cnt); } } intmain() { intT_T,n,m; scanf("%d",&T_T); while(T_T--) { scanf("%d%d",&n,&m); for(inti=1;i<=n;i++) { scanf("%d",sorted+i); tree[0][i]=sorted[i]; } sort(sorted+1,sorted+1+n); build(1,n,0); intl,r,k; while(m--) { scanf("%d%d%d",&l,&r,&k); printf("%d\n",query(1,n,l,r,0,k)); } } return0; } 4.一维RMQ intTU[400]; intdp[400][10]; intRMQ_init() { for(inti=1;i<=m;i++)dp[i][0]=TU[i]; for(intj=1;(1< { for(inti=1;i+(1< { dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } } intRMQ(intL,intR) { intk; while((1<<(k+1))<=(R-L+1))k++; returnmax(dp[L][k],dp[R-(1< } 5.二维RMQ /* 2维RMQ(横向分裂或纵向分裂) */ intdp[10][10][310][310],mp[310][310],n,m; voidRMQ_2D_init() { intmx=floor(log(n+0.0)/log(2.0)); intmy=floor(log(m+0.0)/log(2.0)); for(inti=1;i<=n;i++) for(intj=1;j<=m;j++) dp[0][0][i][j]=mp[i][j]; for(inti=0;i<=mx;i++) { for(intj=0;j<=my;j++) { if(i==0&&j==0)continue; for(introw=1;row+(1< { for(intcol=1;col+(1< { if(i==0) dp[i][j][row][col]=max(dp[i][j-1][row][col],dp[i][j-1]
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM 模板