zoukankan      html  css  js  c++  java
  • 线段树单点更新

    单点更新:最基础的线段树,只更新叶子结点,然后用PushUp函数将信息更新上来。

    HDU1166 敌兵布阵

    线段树功能:update单点增减,query区间求和。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define lson l, mid, root << 1
    #define rson mid + 1, r, root << 1 | 1
    const int maxn = 50005;
    int sum[maxn << 2];
    int t,n;
    char op[10];
    
    void PushUp(int root){
        sum[root] = sum[root << 1] + sum[root << 1 | 1];
    }
    void build(int l,int r,int root)
    {
        if(l == r){
            scanf("%d",&sum[root]);
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);build(rson);
        PushUp(root);
    }
    void update(int pos,int add,int l,int r,int root)
    {
        if(l == r){
            sum[root] += add;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid) update(pos,add,lson);
        else update(pos,add,rson);
        PushUp(root);
    }
    int query(int L,int R,int l,int r,int root)
    {
        if(L <= l && r <= R){
            return sum[root];
        }
        int mid = (l + r) >> 1;
        int ret = 0;
        if(L <= mid) ret += query(L,R,lson);
        if(R > mid) ret += query(L,R,rson);
        return ret;
    }
    int main()
    {
        scanf("%d",&t);
        for(int cas = 1; cas <= t; cas++)
        {
            scanf("%d",&n);
            build(1,n,1);
            printf("Case %d:
    ",cas);
            while(~scanf("%s",op))
            {
                if(op[0] == 'E') break;
                int a,b;
                scanf("%d%d",&a,&b);
                if(op[0] == 'Q'){
                    printf("%d
    ",query(a,b,1,n,1));
                }
                else if(op[0] == 'S'){
                    update(a,-b,1,n,1);
                }
                else{
                    update(a,b,1,n,1);
                }
            }
        }
        return 0;
    }
    View Code

    HDU1754 I Hate It

    线段树功能:update单点替换,query区间最值。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define lson l, mid, root << 1
    #define rson mid + 1, r, root << 1 | 1
    const int maxn = 200005;
    int MAX[maxn << 2];
    int n,m,a,b;
    char op[5];
    
    void PushUp(int root){
        MAX[root] = max(MAX[root <<1],MAX[root << 1 | 1]);
    }
    void build(int l,int r,int root)
    {
        if(l == r){
            scanf("%d",&MAX[root]);
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);build(rson);
        PushUp(root);
    }
    void update(int pos,int src,int l,int r,int root)
    {
        if(l == r){
            MAX[root] = src;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid) update(pos,src,lson);
        else update(pos,src,rson);
        PushUp(root);
    }
    int query(int L,int R,int l,int r,int root)
    {
        if(L <= l && r <= R){
            return MAX[root];
        }
        int mid = (l + r) >> 1;
        int ret = 0;
        if(L <= mid) ret = max(ret,query(L,R,lson));
        if(R > mid) ret = max(ret,query(L,R,rson));
        return  ret;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            build(1,n,1);
            while(m--)
            {
                scanf("%s%d%d",op,&a,&b);
                if(op[0] == 'Q'){
                    printf("%d
    ",query(a,b,1,n,1));
                }
                else{
                    update(a,b,1,n,1);
                }
            }
        }
        return 0;
    }
    View Code

    HDU1394 Minimum Inversion Number

    题意:一个由0...n-1组成的序列,每次将队首的元素移到队尾,求形成的n个序列中最小逆序对数目。

    思路:O(nlogn)复杂度求出最初的逆序对数后,O(1)地推出其他序列的逆序对数。

    线段树功能:update单点增减,query区间求和。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define lson l, mid, root << 1
    #define rson mid + 1, r, root << 1 | 1
    const int maxn = 5005;
    int sum[maxn << 2],x[maxn];
    int n,ans,res;
    
    void PushUp(int root){
        sum[root] = sum[root << 1] + sum[root << 1 | 1];
    }
    void build(int l,int r,int root)
    {
        sum[root] = 0;
        if(l == r)return;
        int mid = (l + r) >> 1;
        build(lson);build(rson);
    }
    void update(int pos,int l,int r,int root)
    {
        if(l == r){
            sum[root]++;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid) update(pos,lson);
        else update(pos,rson);
        PushUp(root);
    }
    int query(int L,int R,int l,int r,int root)
    {
        if(L <= l && r <= R){
            return sum[root];
        }
        int mid = (l + r) >> 1;
        int ret = 0;
        if(L <= mid) ret += query(L,R,lson);
        if(R >= mid) ret += query(L,R,rson);
        return ret;
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            build(0,n-1,1);
            ans = 0;
            for(int i=0;i<n;i++){
                scanf("%d",&x[i]);
                ans += query(x[i],n-1,0,n-1,1);
                update(x[i],0,n-1,1);
            }
            res = ans;
            for(int i=0;i<n;i++){
                ans += n - x[i] - x[i] - 1;
                res = min(res,ans);
            }
            printf("%d
    ",res);
        }
        return 0;
    }
    View Code

     HDU2795 Billboard

    题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子。

    思路:求区间最大值,每次找到最大值的位置然后减去L。实际上就是不断的二分区间寻找合法的位置。

    线段树功能:query区间最大值的位置,update的操作放在了query里面做。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define lson l, mid, root << 1
    #define rson mid + 1, r, root << 1 | 1
    const int maxn = 200005;
    int h,w,n;
    int MAX[maxn << 2];
    
    void PushUp(int root){
        MAX[root] = max(MAX[root << 1],MAX[root << 1 | 1]);
    }
    void build(int l,int r,int root)
    {
        MAX[root] = w;
        if(l == r) return;
        int mid = (l + r) >> 1;
        build(lson);build(rson);
    }
    int query(int x,int l,int r,int root)
    {
        if(l == r){
            MAX[root] -= x;
            return l;
        }
        int mid = (l + r) >> 1;
        int ret = MAX[root << 1] >= x ? query(x,lson) : query(x,rson);
        PushUp(root);
        return ret;
    }
    int main()
    {
        while(~scanf("%d%d%d",&h,&w,&n))
        {
            if(h > n) h = n;
            build(1,h,1);
            while(n--)
            {
                int x;scanf("%d",&x);
                if(MAX[1] < x) puts("-1");
                else printf("%d
    ",query(x,1,h,1));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    docker安装RabbitMQ
    通过Docker安装配置Mysql主从节点
    Docker基本使用命令
    flask接收post提交的json数据并保存至数据库
    前端面经
    js 仿朋友圈的时间显示 刚刚 几天前
    外部div宽度不是100%时,css设置图片宽高相等
    Vue项目图片剪切上传——vue-cropper的使用(二)
    Vue项目图片剪切上传——vue-cropper的使用
    vuex
  • 原文地址:https://www.cnblogs.com/solvit/p/9559527.html
Copyright © 2011-2022 走看看