zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    vb教程图文并茂
    一个文本框的andriod教程
    5月18日,完成导入数据,但是从命令行显示数据乱码,程序已经正常工作
    android 文件读写权限的设定
    raw目录的位置是D:android_projectsqrscanappsrcmain es aw
    一个在raw里面放着数据库文件的网上例子
    P1446 [HNOI2008]Cards [Burnside引理]
    UVA11255 Necklace [Polya定理]
    Polya 定理入门[Burnside引理,Polya定理,欧拉函数]
    P2831 愤怒的小鸟 [状压dp/模拟退火]
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9937781.html
Copyright © 2011-2022 走看看