数据结构部分模版

树状数组

脑子里画出这个图
image

\(\\\)
\(\\\)
\(\\\)
\(\\\)

1.区间查/单点改

int n,m;
int c[Max],a[Max];
int lowbit(int x){return x&-x;}

inline void add(int p,int k)
{
    while(p<=n){c[p]+=k;p+=lowbit(p);}
}

inline int sum(int p)
{
    int ans=0;
    while(p){ans+=c[p];p-=lowbit(p);}
    return ans;
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

2.差分实现区间改/单点查

int n,m;
int c[Max],a[Max];
int lowbit(int x){return x&-x;}

inline void add(int p,int k)
{
    while(p<=n){c[p]+=k;p+=lowbit(p);}
}

inline int sum(int p)
{
    int ans=0;
    while(p){ans+=c[p];p-=lowbit(p);}
    return ans;
}

int main()
{

    cin>>n>>m;
    pos(i,1,n) {cin>>a[i];add(i,a[i]-a[i-1]);}
    pos(i,1,m)
    {
        int x,l,r,k;
        cin>>x;
        if(x==1) 
        {
            cin>>l>>r>>k;
            add(l,k),add(r+1,-k);
        }
        else
        {
            cin>>k;
            cout<<sum(k)<<endl;
        }
    }
    return 0; 
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

3.差分实现区间改/区间查

\[sum[i]=\sum_{j=1}^i c[j] \times(i-j+1) \\ sum[i]=(i+1) \times \sum_{j=1}^i c[j] -\sum_{j=1}^i c[j] \times j \]

int n,m;
int d1[Max],d2[Max],a[Max],b[Max];
int lowbit(int x){return x&-x;}

inline void add(int *c,int p,int k)
{
    while(p<=n){c[p]+=k;p+=lowbit(p);}
}

inline int sum(int *c,int p)
{
    int ans=0;
    while(p){ans+=c[p];p-=lowbit(p);}
    return ans;
}

inline int f(int x)
{
    return b[x]+(x+1)*sum(d1,x)-sum(d2,x);
}

int main()
{
    cin>>n>>m;
    pos(i,1,n) 
    {
        cin>>a[i];
        b[i]=b[i-1]+a[i];
    }
    pos(i,1,m)
    {
        int x,l,r,k;
        cin>>x>>l>>r;
        if(x==1) 
        {
            cin>>k;
            add(d1,l,k),add(d1,r+1,-k),add(d2,l,k*l),add(d2,r+1,-k*(r+1));
        }
        else cout<<f(r)-f(l-1)<<endl; 
    }
    return 0; 
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

4.最值

int m,n;
int a[Max],c[Max],MAX[Max];
char ch;

inline int lowbit(int x){return x&-x;}


void add(int p,int k)
{
    a[p]=k;
    while(p<=n)
    {
        c[p]=max(c[p],k);
        int t=lowbit(p);
        for(int i=1;i<t;i*=2) c[p]=max(c[p],c[p-i]);
        p+=lowbit(p);
    }
}


int query(int l,int r)
{
    int ans=0;
    while(1)
    {
        ans=max(ans,a[r]); 
        if(r==l) break; 
        for(r-=1;r-l>=lowbit(r);r-=lowbit(r)) ans=max(ans,c[r]);
    }
    return ans;
}


signed main()
{
    cin>>n>>m;
    pos(i,1,n) cin>>a[i];
    pos(i,1,n) add(i,a[i]);
    int y,x;
    pos(i,1,m)
    {
		ch=getchar();
		while(ch<'A'||ch>'Z') ch=getchar();
		
        scanf("%lld%lld",&x,&y);
        if(ch=='Q') cout<<query(x,y)<<endl;
        else 
        {
            if(y<=a[x]) continue;
            add(x,y);
        }
    }
    return 0;
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)

线段树

#define mid (s+((t-s)>>1))
#define ls (p<<1)
#define rs ((p<<1)|1)

\(\\\)
\(\\\)
以下代码中
\(s,t\)代表当前区间
\(l,r\)代表询问区间
\(\\\)
\(\\\)

区间修改,区间查询

int n,m;
int a[Max],d[Max*4],b[Max*4];


void pushup(int p)
{
    d[p]=d[ls]+d[rs];
}

void pushdown(int s,int t,int p)
{
    if(b[p]!=0)
    {
        b[ls]+=b[p],b[rs]+=b[p];
        d[ls]+=b[p]*(mid+1-s);
        d[rs]+=b[p]*(t-mid);
        b[p]=0;
    }
    return;
}

void build(int s,int t,int p)
{
    if(s==t) 
    {
        d[p]=a[s];
        return;
    }
    build(s,mid,ls);
    build(mid+1,t,rs);
    pushup(p);
}

int query(int l,int r,int s,int t,int p)
{
    if(l<=s&&t<=r) 
    {
        return d[p];
    }
    int sum=0;
    pushdown(s,t,p);
    if(l<=mid) sum+=query(l,r,s,mid,ls);
    if(r>mid) sum+=query(l,r,mid+1,t,rs);
    return sum;
}

void update(int l,int r,int s,int t,int p,int c)
{
    if(l<=s&&t<=r)
    {
        d[p]+=(t-s+1)*c;
        b[p]+=c;
        return;
    }
    pushdown(s,t,p);
    if(l<=mid) update(l,r,s,mid,ls,c);
    if(r>mid) update(l,r,mid+1,t,rs,c);
    pushup(p);
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

单点修改,区间查询

int n,m;
int a[Max],d[Max*4];

void pushup(int p)
{
    d[p]=d[ls]+d[rs];
}

void build(int s,int t,int p)
{
    if(s==t) 
    {
        d[p]=a[s];
        return;
    }
    build(s,mid,ls);
    build(mid+1,t,rs);
    pushup(p);
}

int query(int l,int r,int s,int t,int p)
{
    if(l<=s&&t<=r) 
    {
        return d[p];
    }
    int sum=0;
    // pushdown(s,t,p);
    if(l<=mid) sum+=query(l,r,s,mid,ls);
    if(r>mid) sum+=query(l,r,mid+1,t,rs);
    return sum;
}

void update(int x,int s,int t,int p,int c)
{
    if(s==t)
    {
        d[p]+=c;
        return;
    }
    // pushdown(s,t,p);
    if(x<=mid) update(x,s,mid,ls,c);
    if(x>mid) update(x,mid+1,t,rs,c);
    pushup(p);
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

单点查询,区间修改

int n,m;
int a[Max],d[Max*4],b[Max*4];

void pushup(int p)
{
    d[p]=d[ls]+d[rs];
}

void pushdown(int s,int t,int p)
{
    if(b[p]!=0)
    {
        b[ls]+=b[p],b[rs]+=b[p];
        d[ls]+=b[p]*(mid+1-s);
        d[rs]+=b[p]*(t-mid);
        b[p]=0;
    }
    return;
}

void build(int s,int t,int p)
{
    if(s==t)
    {
        d[p]=a[s];
        return;
    }
    build(s,mid,ls);
    build(mid+1,t,rs);
    pushup(p);
}

int query(int x,int s,int t,int p)
{
    if(s==t)
    {
        return d[p];
    }
    pushdown(s,t,p);
    if(x<=mid)  return query(x,s,mid,ls);
    if(x>mid) return query(x,mid+1,t,rs);
}

void update(int l,int r,int s,int t,int p,int c)
{
    if(l<=s&&t<=r)
    {
        d[p]+=c*(t-s+1);
        b[p]+=c;
        return;
    }
    pushdown(s,t,p);
    if(l<=mid) update(l,r,s,mid,ls,c);
    if(r>mid) update(l,r,mid+1,t,rs,c);
    pushup(p);
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)

主席树

\(\\\)
image
\(\\\)

1

int cnt,n,m;
int a[Max],root[Max];

struct Tree
{
    int l,r,val;
}tree[Max];

int clone(int p)
{
    cnt++;
    tree[cnt]=tree[p];
    return cnt;
}

int build(int p,int s,int t)
{
    p=++cnt;
    if(s==t)
    {
        tree[cnt].val=a[s];
        return p;
    }
    tree[p].l=build(tree[p].l,s,mid);
    tree[p].r=build(tree[p].r,mid+1,t);
	return p;
}

int update(int p,int s,int t,int x,int v)
{
    p=clone(p);
    if(s==t)
    {
        tree[p].val=v;
        return p;
    }
    if(x<=mid) tree[p].l=update(tree[p].l,s,mid,x,v);
    if(x>mid) tree[p].r=update(tree[p].r,mid+1,t,x,v);
    return p;
}

int query(int p,int s,int t,int x)
{
    if(s==t) return tree[p].val;

    if(x<=mid) return query(tree[p].l,s,mid,x);
    else return query(tree[p].r,mid+1,t,x);
}

signed main()
{
    cin>>n>>m;
    pos(i,1,n) cin>>a[i];
    root[0]=build(0,1,n);
    return 0;
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

区间第k小

int clone(int p)
{
    cnt++;
    tree[cnt]=tree[p];
    tree[cnt].val++;
    return cnt;
}

int build(int p,int s,int t)
{
    p=++cnt;
    if(s==t)
    {
//        tree[cnt].val=a[s];
        return p;
    }
    tree[p].l=build(tree[p].l,s,mid);
    tree[p].r=build(tree[p].r,mid+1,t);
	return p;
}

int update(int p,int s,int t,int x,int v)
{
    p=clone(p);
    if(s==t)
    {
//        tree[p].val+=v;
        return p;
    }
    if(x<=mid) tree[p].l=update(tree[p].l,s,mid,x,v);
    if(x>mid) tree[p].r=update(tree[p].r,mid+1,t,x,v);
    return p;
}

int query1(int p,int q,int s,int t,int k)
{
    int x=tree[tree[p].l].val-tree[tree[q].l].val;
    if(s==t) return b[s];
    if(x>=k) return query1(tree[p].l,tree[q].l,s,mid,k);
    else  return query1(tree[p].r,tree[q].r,mid+1,t,k-x);
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        b[i]=a[i];
    }
    sort(b+1,b+1+n);
    int nn=unique(b+1,b+1+n)-b-1;
    rt[0]=build(0,1,nn);
    for(int i=1;i<=n;i++)
    {
        int x=lower_bound(b+1,b+1+nn,a[i])-b;
        rt[i]=update(rt[i-1],1,nn,x,1);
    }
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        cout<<query1(rt[y],rt[x-1],1,nn,z)<<"\n";
    }
    return 0;
}
posted @ 2022-02-12 17:55  juuich  阅读(17)  评论(0编辑  收藏  举报