zoukankan      html  css  js  c++  java
  • 算法笔记--线段树

    算法笔记

    模板:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define pb push_back
    const int INF=0x3f3f3f3f;
    const int N=1e6+5;
    int tree[4*N];
    int lazy[4*N]; 
    //将子节点值更新到父亲节点
    /*对于区间求和而言*/ 
    void push_up(int rt)
    {
        tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    }
    //节点懒惰标记下推 
    /*对于区间求和而言*/
    void push_down(int rt,int len)
    {
        tree[rt<<1]+=lazy[rt]*(len-(len>>1));
        lazy[rt<<1]+=lazy[rt];
        tree[rt<<1|1]+=lazy[rt]*(len>>1);
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    } 
    //建树
    void build(int rt,int l,int r)
    {
        if(l==r)
        {
            scanf("%d",&tree[rt]);//最好用scanf,防止超时
            return ;
        }
        int m=(l+r)>>1;
        build(ls);
        build(rs);
        push_up(rt);
    } 
    //单节点更新 
    void update(int p,int delta,int rt,int l,int r)
    {
        if(l==r)
        {
            tree[rt]+=delta;
            return ;
        }
        int m=(l+r)>>1;
        if(p<=m)update(p,delta,ls);
        else update(p,delta,rs);
        push_up(rt);
    }
    //区间更新
    void Update(int L,int R,int delta,int rt,int l,int r)
    {
        if(L<=l&&r<=R)
        {
            tree[rt]+=(r-l+1)*delta;
            lazy[rt]+=delta;
            return ;
        }
        if(lazy[rt])push_down(rt,r-l+1);
        int m=(l+r)>>1;
        if(L<=m)Update(L,R,delta,ls);
        if(R>m)Update(L,R,delta,rs);
        push_up(rt); 
    } 
    //区间查询
    /*对于区间求和而言*/
    int query(int L,int R,int rt,int l,int r)
    {
        if(L<=l&&r<=R)return tree[rt];
        if(lazy[rt])push_down(rt,r-l+1);
        int m=(l+r)>>1,res=0;
        if(L<=m)res+=query(L,R,ls);
        if(R>m)res+=query(L,R,rs);
        return res;
    } 

    POJ - 3468A Simple Problem with Integers

    代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define ll long long
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define pb push_back
    const int INF=0x3f3f3f3f;
    const int N=1e5+5;
    ll tree[4*N];
    ll lazy[4*N]; 
    void push_up(int rt)
    {
        tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    }
    void push_down(int rt,int len)
    {
        tree[rt<<1]+=lazy[rt]*(len-(len>>1));
        lazy[rt<<1]+=lazy[rt];
        tree[rt<<1|1]+=lazy[rt]*(len>>1);
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
    void build(int rt,int l,int r)
    {
        if(l==r)
        {
            scanf("%lld",&tree[rt]);
            return ;
        }
        int m=(l+r)>>1;
        build(ls);
        build(rs);
        push_up(rt);
    }
    void Update(int L,int R,int delta,int rt,int l,int r)
    {
        if(L<=l&&r<=R)
        {
            tree[rt]+=delta*(r-l+1);
            lazy[rt]+=delta;
            return;
        }
        if(lazy[rt])push_down(rt,r-l+1);
        int m=(l+r)>>1;
        if(L<=m)Update(L,R,delta,ls);
        if(R>m)Update(L,R,delta,rs);
        push_up(rt);
    }
    ll query(int L,int R,int rt,int l,int r)
    {
        if(L<=l&&r<=R)return tree[rt];
        if(lazy[rt])push_down(rt,r-l+1);
        int m=(l+r)>>1;
        ll res=0;
        if(L<=m)res+=query(L,R,ls);
        if(R>m)res+=query(L,R,rs);
        return res;
    } 
    int main()
    {
        /*ios::sync_with_stdio(false);
        cin.tie(0);*/
        int n,q;
        scanf("%d%d",&n,&q);
        build(1,1,n);
        while(q--)
        {
            getchar();
            char s;
            int a,b,c;
            scanf("%c",&s);
            if(s=='Q')
            {
                scanf("%d%d",&a,&b);
                printf("%lld
    ",query(a,b,1,1,n));
            }
            else
            {
                scanf("%d%d%d",&a,&b,&c);
                Update(a,b,c,1,1,n);
            }
        }
        return 0;
    } 
    View Code

     HDU 1698

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    int lazy[4*N];
    int tree[4*N];
    void push_up(int rt)
    {
        tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    }
    void push_down(int rt,int len)
    {
        lazy[rt<<1]=lazy[rt];
        lazy[rt<<1|1]=lazy[rt];
        tree[rt<<1]=lazy[rt]*(len-(len>>1));
        tree[rt<<1|1]=lazy[rt]*(len>>1);
        lazy[rt]=0;
    }
    void build(int rt,int l,int r)
    {
        lazy[rt]=0;
        if(l==r)
        {
            tree[rt]=1;
            return  ;
        }
        int m=(l+r)>>1;
        build(ls);
        build(rs);
        push_up(rt);
    }
    /*void update(int p,int delta,int rt,int l,int r)
    {
        if(l==r)
        {
            tree[rt]=delta;
            return ;
        }
        int m=(l+r)>>1;
        if(p<=m)update(p,delta,ls);
        else update(p,delta,rs);
        push_up(rt);
    }*/
    void Update(int L,int R,int delta,int rt,int l,int r)
    {
        if(L<=l&&r<=R)
        {
            tree[rt]=delta*(r-l+1);
            lazy[rt]=delta;
            return ;
        }
        if(lazy[rt])push_down(rt,r-l+1);
        int m=(l+r)>>1;
        if(L<=m)Update(L,R,delta,ls);
        if(R>m)Update(L,R,delta,rs);
        push_up(rt);
    }
    int query(int L,int R,int rt,int l,int r)
    {
        if(L<=l&&r<=R)return tree[rt];
        if(lazy[rt])push_down(rt,r-l+1);
        int m=(l+r)>>1,ans=0;
        if(L<=m)ans+=query(L,R,ls);
        if(R>m)ans+=query(L,R,rs);
        return ans;
    }
    int main()
    {
        /*ios::sync_with_stdio(false);
        cin.tie(0);*/
        int T,n,q,l,r,a;
        scanf("%d",&T);
        int cs=0;
        while(T--)
        {
            scanf("%d",&n);
            build(1,1,n);
            scanf("%d",&q);
            while(q--)
            {
                scanf("%d%d%d",&l,&r,&a);
                Update(l,r,a,1,1,n);
            }
            printf("Case %d: The total value of the hook is %d.
    ",++cs,query(1,n,1,1,n));
            //for(int i=1;i<=2*n;i++)cout<<tree[i]<<endl;
        }
        return 0;
    }
    View Code

    ZOJ 1610

    #include<bits/stdc++.h>
    using namespace std;
    #define long long
    #define pb push_back
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=8e3+5;
    int vis[N];
    int ans[N];
    int lazy[N<<2];
    void push_down(int rt)
    {
        lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
        lazy[rt]=-1;
    }
    void update(int L,int R,int c,int rt,int l,int r)
    {
        if(L<=l&&r<=R)
        {
            lazy[rt]=c;
            return ;
        }
        if(lazy[rt]==c)return ;
        if(lazy[rt]!=-1)push_down(rt);
        int m=(l+r)>>1;
        if(L<=m)update(L,R,c,ls);
        if(R>m)update(L,R,c,rs);
    }
    void query(int L,int R,int rt,int l,int r)
    {
        if(lazy[rt]!=-1)
        {
            for(int i=l;i<=r;i++)
            vis[i]=lazy[rt];
            return ;
        }
        if(l!=r&&lazy[rt]==-1)
        {
            int m=(l+r)>>1;
            if(L<=m)query(L,R,ls);
            if(R>m)query(L,R,rs);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,l,r,c;
        while(cin>>n)
        {
            mem(lazy,-1);
            mem(vis,-1);
            mem(ans,0);
            for(int i=0;i<n;i++)cin>>l>>r>>c,update(l+1,r,c,1,1,8000);
            //cout<<1<<endl;
            query(1,8000,1,1,8000);
            int i=1;
            while(i<N)
            {
                if(vis[i]==-1){
                    i++;
                    continue;
                }
                int c=vis[i];
                while(i<N&&vis[i]==c)i++;
                ans[c]++;
            }
            for(int i=0;i<N;i++)if(ans[i])cout<<i<<' '<<ans[i]<<endl;
            cout<<endl;
        }
        return 0;
    }
    View Code

    POJ 3264

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define mem(a,b) memset(a,b,sizeof(a))
    const int N=5e4+5;
    const int INF=0x3f3f3f3f;
    struct node
    {
        int mx,mn;    
    }tree[N<<2];
    void push_up(int rt)
    {
        tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
        tree[rt].mn=min(tree[rt<<1].mn,tree[rt<<1|1].mn);
    }
    void build(int rt,int l,int r)
    {
        if(l==r)
        {
            scanf("%d",&tree[rt].mx);
            tree[rt].mn=tree[rt].mx;
            return ;
        }
        int m=(l+r)>>1;
        build(ls);
        build(rs);
        push_up(rt);
    }
    int querymx(int L,int R,int rt,int l,int r)
    {
        if(L<=l&&r<=R)return tree[rt].mx;
        int m=(l+r)>>1,ans=0;
        if(L<=m)ans=max(ans,querymx(L,R,ls));
        if(R>m)ans=max(ans,querymx(L,R,rs));
        return ans;
    }
    int querymn(int L,int R,int rt,int l,int r)
    {
        if(L<=l&&r<=R)return tree[rt].mn;
        int m=(l+r)>>1,ans=INF;
        if(L<=m)ans=min(ans,querymn(L,R,ls));
        if(R>m)ans=min(ans,querymn(L,R,rs));
        return ans;
    } 
    int main()
    {
        /*ios::sync_with_stdio(false);
        cin.tie(0);*/
        int n,q,l,r;
        scanf("%d%d",&n,&q);
        build(1,1,n);
        while(q--)
        {
            scanf("%d%d",&l,&r);
            printf("%d
    ",querymx(l,r,1,1,n)-querymn(l,r,1,1,n));
        }
        return 0;    
    } 
    View Code

    HDU 4027

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define pb push_back
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    ll tree[N<<2];
    void push_up(int rt)
    {
        tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    } 
    void build(int rt,int l,int r)
    {
        if(l==r)
        {
            scanf("%lld",&tree[rt]);
            return ;
        }
        int m=(l+r)>>1;
        build(ls);
        build(rs);
        push_up(rt);
    }
    void update(int L,int R,int rt,int l,int r)
    {
        if(l==r)
        {
            tree[rt]=(int)sqrt(tree[rt]);
            return ;
        }
        int m=(l+r)>>1;
        if(L<=m)update(L,R,ls);
        if(R>m)update(L,R,rs);
        push_up(rt); 
    }
    ll query(int L,int R,int rt,int l,int r)
    {
        if(L<=l&&r<=R)return tree[rt];
        int m=(l+r)>>1;
        ll ans=0;
        if(L<=m)ans+=query(L,R,ls);
        if(R>m)ans+=query(L,R,rs);
        return ans;
    }
    int main()
    {
        int n,m,t,l,r,cs=0;
        while(~scanf("%d",&n))
        {
            build(1,1,n);
            scanf("%d",&m);
            printf("Case #%d:
    ",++cs);
            while(m--)
            {
                scanf("%d%d%d",&t,&l,&r);
                if(l>r)swap(l,r);
                if(t==0)
                {
                    if(query(l,r,1,1,n)!=r-l+1)update(l,r,1,1,n);
                }
                else
                {
                    printf("%lld
    ",query(l,r,1,1,n));
                }
            }
            puts("");
        }
        return 0;    
    } 
    View Code

    HDU 1540

    线段树区间合并

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=5e4+5;
    struct tree{
        int ll,rr,len;//ll表示以当前区间左端点为左端点最长连续区间的长度,rr表示以当前区间右端点为右端点最长连续区间的长度,len表示当前区间的长度
    }tree[N<<2];
    void push_up(int rt){
        if(tree[rt<<1].ll==tree[rt<<1].len)tree[rt].ll=tree[rt<<1].ll+tree[rt<<1|1].ll;
        else tree[rt].ll=tree[rt<<1].ll;
        if(tree[rt<<1|1].rr==tree[rt<<1|1].len)tree[rt].rr=tree[rt<<1|1].rr+tree[rt<<1].rr;
        else tree[rt].rr=tree[rt<<1|1].rr;
    }
    void build(int rt,int l,int r){
        tree[rt].ll=tree[rt].rr=tree[rt].len=r-l+1;
        if(l==r)return ;
        int m=(l+r)>>1;
        build(ls);
        build(rs);
    }
    void update(int p,int v,int rt,int l,int r){
        if(l==r){
            tree[rt].ll=tree[rt].rr=v;
            return ;
        }
        int m=(l+r)>>1;
        if(p<=m)update(p,v,ls);
        else update(p,v,rs);
        push_up(rt);
    }
    int query(int p,int rt,int l,int r){
        if(rt==1){
            if(l+tree[rt].ll-1>=p)return tree[rt].ll;
            if(r-tree[rt].rr+1<=p)return tree[rt].rr;
        }
        else{
            if(l+tree[rt].ll-1>=p)return tree[rt].ll+tree[rt-1].rr;
            if(r-tree[rt].rr+1<=p)return tree[rt].rr+tree[rt+1].ll;
        }
        if(l==r)return 0;
        int m=(l+r)>>1;
        if(p<=m)return query(p,ls);
        else return query(p,rs);
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m,x;
        char c;
        while(cin>>n>>m){
            stack<int>s;
            build(1,1,n);
            while(m--){
                cin>>c;
                if(c=='D'){
                    cin>>x;
                    s.push(x);
                    update(x,0,1,1,n);
                }
                else if(c=='Q'){
                    cin>>x;
                    cout<<query(x,1,1,n)<<endl;
                }
                else{
                    x=s.top();
                    s.pop();
                    update(x,1,1,1,n);
                }
            }
        }
        return 0;
    }
    View Code

    HDU 3974

    dfs序+线段树

    先将每个节点按dfs序的in[u]映射到线段上,然后将线段映射成线段树

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=5e4+5;
    int head[N];
    int in[N];
    int ind[N];
    int out[N];
    int tree[N<<2];
    int lazy[N<<2];
    struct edge{
        int to,next;
    }edge[N];
    int cnt=0;
    void add_edge(int u,int v){
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dfs(int u,int &x){
        in[u]=x;
        for(int i=head[u];~i;i=edge[i].next)dfs(edge[i].to,++x);
        out[u]=x;
    }
    void push_down(int rt){
        if(lazy[rt]){
            tree[rt<<1]=lazy[rt];
            tree[rt<<1|1]=lazy[rt];
            lazy[rt<<1]=lazy[rt];
            lazy[rt<<1|1]=lazy[rt];
            lazy[rt]=0;
        }
    }
    void update(int L,int R,int v,int rt,int l,int r){
        if(L<=l&&r<=R){
            tree[rt]=v;
            lazy[rt]=v;
            return ;
        }
        push_down(rt);
        int m=(l+r)>>1;
        if(L<=m)update(L,R,v,ls);
        if(R>m)update(L,R,v,rs);
    }
    int query(int p,int rt,int l,int r){
        if(l==r)return tree[rt];
        push_down(rt);
        int m=(l+r)>>1;
        if(p<=m)return query(p,ls);
        else return query(p,rs);
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0);
        int T,cs=0;
        cin>>T;
        while(T--){
            mem(head,-1);
            mem(ind,0);
            cnt=0;
            int n,rt,u,v,l,r,m;
            char c;
            cin>>n;
            for(int i=1;i<n;i++){
                cin>>u>>v;
                add_edge(v,u);
                ind[u]++;
            }
            for(int i=1;i<=n;i++)if(ind[i]==0)rt=i;
            int x=1;
            dfs(rt,x);
            mem(tree,-1);
            mem(lazy,0);
            cout<<"Case #"<<++cs<<":"<<endl;
            cin>>m;
            while(m--){
                cin>>c;
                if(c=='C'){
                    cin>>l;
                    cout<<query(in[l],1,1,n)<<endl;
                }
                else {
                    cin>>l>>r;
                    update(in[l],out[l],r,1,1,n);
                }
            }
        }
        return 0;
    }
    View Code

    线段树易错点:

    1.push_down后记得push_up

    2.区间修改或者查询应该有两个if判断if(L <= m); if(R > m);很容易写成if(L <= m); else ;这是不对的

    3.lazy标记的修改很容易错

  • 相关阅读:
    MySQL--单表查询
    python库--pandas--Series.str--字符串处理
    如何 grep tab & 如何grep 减号(dash)
    png压缩
    如何无密码登陆远程机器?
    ssh中运行awk
    PHP 时区
    sublime使用
    nginx 50x故障分析
    nginx反向代理异常
  • 原文地址:https://www.cnblogs.com/widsom/p/7266465.html
Copyright © 2011-2022 走看看