zoukankan      html  css  js  c++  java
  • HDU 4288 Coder (线段树)

    Coder


    题意:有三种类型的操作,(1)."add x",表示往集合里加入�数x。(2).“del x”表示将集合中数x删除。(3).“sum”求出从小到大排列的集合中下标模5为3的数的和。集合中的数都是唯一的。

    思路:这题巧妙的地方在于先离线输入,然后离散化。输入的数字依照从小到大排序,然后作为线段树的叶子结点。每一个结点包括两个部分,一是该结点包括的数字个数,二是依照区间内模5的余数分组求和。当须要向上pushup时,左子树的区间不变,而右子树的区间内,每一个数字的位置发生改变,一開始为i,之后变为i+cnt(cnt表示左子树区间内数字个数)

    代码:
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<string>
    #include<fstream>
    #include<cstring>
    #include<ctype.h>
    #include<iostream>
    #include<algorithm>
    #define INF (1<<30)
    #define PI acos(-1.0)
    #define mem(a, b) memset(a, b, sizeof(a))
    #define rep(i, n) for (int i = 0; i < n; i++)
    #define debug puts("===============")
    typedef long long ll;
    using namespace std;
    const int maxn = 100200;
    ll sum[maxn << 2][5];
    int cnt[maxn << 2];
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    int n, tot, op[maxn], a[maxn];
    char str[maxn][10];
    void pushup(int rt) {
        cnt[rt] = cnt[rt << 1] + cnt[rt << 1 | 1];
        int p = cnt[rt << 1];
        for (int i = 0; i < 5; i++) {
            sum[rt][i] = sum[rt << 1][i] + sum[rt << 1 | 1][((i - p) % 5 + 5) % 5];
        }
        //cout<<rt<<" "<<cnt[rt]<<endl;
    }
    void update(int pos, int x, int l, int r, int rt) {
        if (l == r) {
            if (x == 1) {
                sum[rt][1] = a[pos - 1];
                cnt[rt] = 1;
            } else {
                sum[rt][1] = 0;
                cnt[rt] = 0;
            }
            return ;
        }
        int m = (l + r) >> 1;
        if (pos <= m) update(pos, x, lson);
        else update(pos, x, rson);
        pushup(rt);
    }
    void build(int l, int r, int rt) {
        for (int i = 0; i < 5; i++) sum[rt][i] = 0;
        cnt[rt] = 0;
        if (l == r) return ;
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
    }
    int main () {
        while(~scanf("%d", &n)) {
            tot = 0;
            for (int i = 0; i < n; i++) {
                scanf("%s", str[i]);
                if (str[i][0] != 's') {
                    scanf("%d", op + i);
                    a[tot++] = op[i];
                }
            }
            sort(a, a + tot);
            tot = unique(a, a + tot) - a;
            build(1, tot, 1);
            for (int i = 0; i < n; i++) {
                if (str[i][0] == 's') printf("%I64d
    ", sum[1][3]);
                else {
                    int pos = lower_bound(a, a + tot, op[i]) - a + 1;
                    if (str[i][0] == 'a') update(pos, 1, 1, tot, 1);
                    else update(pos, -1, 1, tot, 1);
                }
            }
        }
        return 0;
    }<strong>
    </strong>


  • 相关阅读:
    (原)Lazarus 异构平台下多层架构思路、DataSet转换核心代码
    (学)新版动态表单研发,阶段成果3
    (学) 如何将 Oracle 序列 重置 清零 How to reset an Oracle sequence
    (学)XtraReport WebService Print 报错
    (原)三星 i6410 刷机 短信 无法 保存 解决 办法
    (原) Devexpress 汉化包 制作工具、测试程序
    linux下网络配置
    apache自带ab.exe小工具使用小结
    Yii::app()用法小结
    PDO使用小结
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4057202.html
Copyright © 2011-2022 走看看