• FJUT3574 HOME_W的附加题(带权线段树)题解


    题意:

    给定n个数a1,a2,a3,……an。和m次操作。

    每次操作格式如下

    x y k   表示将a[x]替换为y。并求替换后,前k小的数之和

    思路:我们用带权线段树维护权值,这里就是维护i的个数num[i],然后顺便维护一下和。每次查询前k个数求和。

    练习赛题解:

    代码:

    #include<set>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    const int maxn = 100000 + 10;
    const int seed = 131;
    const ll MOD = 1e9 + 7;
    const ll INF = 1e17;
    using namespace std;
    int num[maxn << 2], a[maxn], b[maxn];
    ll sum[maxn << 2];
    void build(int l, int r, int rt){
        if(l == r){
            num[rt] = a[l];
            sum[rt] = l * num[rt];
            return;
        }
        int m = (l + r) >> 1;
        build(l, m, rt << 1);
        build(m + 1, r, rt << 1 | 1);
        num[rt] = num[rt << 1] + num[rt << 1 | 1];
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    void update(int pos, int l, int r, int rt, int v){
        if(l == r){
            num[rt] += v;
            sum[rt] = l * num[rt];
            return;
        }
        int m = (l + r) >> 1;
        if(pos <= m)
            update(pos, l, m, rt << 1, v);
        else
            update(pos, m + 1, r, rt << 1 | 1, v);
        num[rt] = num[rt << 1] + num[rt << 1 | 1];
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    ll query(int l, int r, int rt, int k){
        if(l == r){
            return l * k;
        }
        int m = (l + r) >> 1;
        ll ans = 0;
        if(num[rt << 1] >= k){
            ans += query(l, m, rt << 1, k);
        }
        else{
            ans += sum[rt << 1];
            ans += query(m + 1, r, rt << 1 | 1, k - num[rt << 1]);
        }
        return ans;
    }
    int main(){
        int n, m;
        memset(a, 0, sizeof(a));
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++){
            scanf("%d", &b[i]);
            a[b[i]]++;
        }
        build(1, 100000, 1);
        int x, y, k;
        for(int i = 0; i < m; i++){
            scanf("%d%d%d", &x, &y, &k);
            update(b[x], 1, 100000, 1, -1);
            update(y, 1, 100000, 1, 1);
            b[x] = y;
            printf("%lld
    ", query(1, 100000, 1, k));
        }
        return 0;
    }
  • 相关阅读:
    RAID磁盘阵列
    Activiti任务认领
    Activiti 5.18启动流程到完成所有任务之间的数据库变化(转)
    tomcat优化(转)
    DB2 OLAP函数的使用
    PreparedStatement批量处理和事务
    获取JavaScript异步函数的返回值
    DB2 sql报错后查证原因与解决问题的方法
    DB2有五种约束
    连接db2数据库出现No buffer space available (maximum connections reached?)
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9937781.html
Copyright © 2020-2023  润新知