[关闭]
@AkamemakA 2022-09-11T06:27:14.000000Z 字数 2241 阅读 126

模板 知识点 算法

模板速查


一.线段树(区间求和为例)

  1. #define lson (p<<1)
  2. #define rson (p<<1|1)

1.建树

  1. inline void build(int p,int l,int r){
  2. t[p].l=l,t[p].r=r; //每一部分的左右端点
  3. if(l==r){ //叶子节点
  4. t[p].sum=a[l];
  5. //创建所要维护的内容
  6. return ;
  7. }
  8. int mid=l+r>>1;
  9. build(lson,l,mid); //建左子树
  10. build(rson,mid+1,r); //建右子树
  11. pushup(p); //得到所维护内容
  12. }

2.区间修改

区间+

  1. inline void change(int p,int l,int r,ll k){
  2. if(t[p].l>=l&&t[p].r<=r){ //当前区间完全包含于所求区间
  3. t[p].sum+=k*(t[p].r-t[p].l+1); //直接加上
  4. t[p].lazy+=k; //更新懒标记
  5. return ;
  6. }
  7. pushdown(p); //标记下传
  8. int mid=l+r>>1;
  9. if(t[lson].r>=l) change(lson,l,r,k); //若左子树与所求区间有交集,则递归左子树求值
  10. if(t[rson].l<=r) change(rson,l,r,k); //右子树同理
  11. pushup(p) //更新所维护内容
  12. }

3.区间查询

  1. inline int query(int p,int l,int r){
  2. if(t[p].l>=l&&t[p].r<=r)return t[p].sum; ///当前区间完全包含于所求区间,直接返回当前区间的值
  3. pushdown(p); //标记下传
  4. int res=0;
  5. if(t[lson].r>=l) res+=query(lson,l,r);
  6. if(t[rson].l<=r) res+=query(rson,l,r);
  7. return res;
  8. }

二.树状数组

1.单点修改(+k)

  1. inline void updata(int x,int y){
  2. for(int i=x;i<=n;i+=lowbit(i))
  3. c[i]+=y;
  4. }

2.区间查询(求和)

  1. inline int query(int x){
  2. int res=0;
  3. for(int i=x;i;i-=lowbit(i))
  4. res+=c[i];
  5. return res;
  6. }

三.线性基

1.建基

  1. inline void ins(int x){
  2. for(int i=62;i>=0;i--){
  3. if(!((x>>i)&1)) continue;
  4. if(!p[i]){
  5. p[i]=x;
  6. break;
  7. }
  8. x^=p[i];
  9. }
  10. }

2.求任意异或的最大值

  1. int ans=0;
  2. for(int i=62;i>=0;i--)
  3. if((ans^p[i])>ans)
  4. ans^=p[i];

四.强连通分量(缩点)

  1. inline void tarjan(int u){
  2. dfn[u]=low[u]=++cnt;
  3. sta[++tp]=u;st[u]=1;
  4. for(int i=he[u];i;i=ne[i]){
  5. int v=go[i];
  6. if(!dfn[v]){
  7. tarjan(v);
  8. low[u]=min(low[u],low[v]);
  9. }else if(st[v]) low[u]=min(low[u],dfn[v]);
  10. }
  11. if(dfn[u]==low[u]){
  12. scc++;int t;
  13. do{
  14. t=sta[tp--];
  15. id[t]=scc;
  16. st[t]=0;
  17. vul[scc]+=val[t];
  18. }while(t!=u);
  19. }
  20. }

五.KMP模式匹配法

1.求失配数组

  1. int j=0;
  2. for(int i=2;i<=lt;i++){
  3. while(j&&t[i]!=t[j+1]) j=ne[j];
  4. if(t[i]==t[j+1]) j++;
  5. ne[i]=j;
  6. }

2.匹配

  1. j=0;
  2. for(int i=1;i<=ls;i++){
  3. while(j&&s[i]!=t[j+1]) j=ne[j];
  4. if(s[i]==t[j+1]) j++;
  5. if(j==lt) cout<<i-lt+1<<endl;
  6. }

六.高斯消元法

  1. inline void Gauss(){
  2. for(int r=1,c=1;c<=n;r++,c++){
  3. int mai=r;
  4. for(int i=r+1;i<=n;i++)
  5. if(fabs(a[i][c])>fabs(a[mai][c]))mai=i;
  6. for(int i=c;i<=n+1;i++)
  7. swap(a[mai][i],a[r][i]);
  8. if(a[r][c]==0){
  9. puts("No Solution");
  10. exit(0);
  11. }//无解或有自由元
  12. for(int i=n+1;i>=c;i--)
  13. a[r][i]/=a[r][c];
  14. for(int i=r+1;i<=n;i++)
  15. for(int j=n+1;j>=c;j--)
  16. a[i][j]-=a[r][j]*a[i][c];
  17. }
  18. for(int i=n;i>1;i--)
  19. for(int j=i-1;j>=1;j--){
  20. a[j][n+1]-=a[i][n+1]*a[j][i];
  21. a[j][i]=0;
  22. }
  23. }

七.单调队列

  1. int head=1,tail=1;
  2. for(int i=1;i<=n;i++){
  3. while(num[head]<i-k+1&&head<=tail) head++;
  4. while(a[num[tail]]>=a[i]&&head<=tail) tail--;
  5. num[++tail]=i;
  6. if(i>=k)printf("%d ",a[num[head]]);
  7. }//求所有长度为k的区间中的最小值

八.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注