Extention

D-数据结构

D1-序列结构

树状数组

lowbit(x)x&(-x) 得到 最低位的 1 以及若干后缀 0。

管辖范围

建树 :做前缀和,

时间优化

可动态维护前缀和

区间修改单点查询:差分。

查询第 k 小数:权值树状数组存储每个值的出现次数。

 int kth(int k){
 int ans=0,ct=0;
 for(int i=tot;i>=0;i--){
 ans+=(1<<i);
 if(ans>N||ct+c[ans]>=k) ans-=(1<<i);
 else ct+=c[ans];
 }
 return ++ans;
 }

线段树

动态开点线段树 & 线段树合并 & 线段树分裂
  • 动态开点线段树可以使用懒标记,下传标记时需要新建结点(若标记对空节点无影响则不必新建节点)。

  • 遇到仅针对某个权值的修改和询问时,可以考虑对每个权值开一个动态开点线段树。

  • 线段树合并单次复杂度,取决于两棵线段树的交集大小;线段树合并总复杂度,取决于所有线段树的节点总数。

  • 线段树合并支持持久化,需要在合并时新建节点。

  • 在线段树合并的过程中,可以统计来自不同线段树且具有相对顺序关系的信息。例如逆序对。

  • 在线段树合并的过程中,在处理复杂的问题时,可以尝试分成以下几类讨论(其中 2, 3 是讨论重点):

    • (1)p,q 均为空节点:返回空节点。

    • (2)p,q 中分别有一个空节点和一个非空节点:特殊讨论。

    • (3)线段树递归到叶子节点(即 l=r):特殊讨论。

    • (4)p,q 均为非空节点:分别合并 p,q 的左儿子与 p,q 的右儿子,最后 update。

  • 线段树分裂单次复杂度 O(logA),新建节点个数 O(logA)。

 namespace SGT{
     #define mid ((l+r)>>1)
     #define lc(k) t[k].ls
     #define rc(k) t[k].rs
 
     const int pd=...;
     int tot=0,rt[N];
     struct node{
         int ls,rs,ct;
    }t[pd];
     void upd(int k){
         t[k].ct=t[lc(k)].ct+t[rc(k)].ct;
    }
     void ins(int &k,int l,int r,int x,int w){
         if(!k) k=++tc;
         if(l==r) return t[k].ct+=w,void();
         if(x<=mid) ins(lc(k),l,mid,x,w);
         else ins(rc(k),mdi+1,r,x,w);
         upd(k);
    }
     int merge(int p,int q){
         if(!p||!q) return p^q;
         t[p].ct+=t[q].ct;
         lc(p)=merge(lc(p),lc(q));
         rc(p)=merge(rc(p),rc(q));
         return p;
    }
     /*可持久化线段树合并
     int merge(int p,int q){
         if(!p||!q) return p^q;
         int u=++tot;
         t[u].ct=t[p].ct+t[q].ct;
         lc(u)=merge(lc(p),lc(q));
         rc(u)=merge(rc(p),rc(q));
         return u;
     }
     */
     void split_w(int p,int l,int r,int w,int &x,int &y){//动态开点权值线段树
         if(!p) return x=y=0,void();
         if(mid<w)
             x=p,y=++tot,split_w(rc(p),mid+1,r,w,rc(x),rc(y));
         else if(mid==w)
             x=++tot,y=++tot,lc(x)=lc(p),rc(y)=rc(p);
         else y=p,x=++tot,split_w(lc(p),l,mid,lc(x),lc(y));
         upd(x),upd(y);
    }
     void split_s(int p,int l,int r,int s,int &x,int &y){
         if(!p) return x=y=0,void();
         if(t[lc(p)].cnt<s)
             x=p,y=++tot,split_s(rc(p),mid+1,r,s,rc(x),rc(y));
         else if(t[lc(p)].cnt==s)
             x=++tot,y=++tot,lc(x)=lc(p),rc(y)=rc(p);
         else y=p,x=++tot,split_s(lc(p),l,mid,s,lc(x),lc(y));
         upd(x),upd(y);
    }
 }
主席树
 namespace SGT{
     #define mid ((l+r)>>1)
     #define lc(k) t[k].ls
     #define rc(k) t[k].rs
 
     const int pd=...;
     int tot=0,rt[N];
     struct node{
         int ls,rs,ct;
    }t[pd];
     void ins(int &p,int q,int l,int r,int x,int w){
         p=++tot;t[p]=t[q];
         t[p].ct+=w;//沿路加上,无需再 upd
         if(l==r) continue;
         if(x<=mid) ins(lc(p),lc(q),l,mid,x,w);
         else ins(rc(p),rc(q),mid+1,r,x,w);
    }
 }
 
posted @ 2025-03-01 23:53  西西西嘻  阅读(23)  评论(0)    收藏  举报