Codeforces 85D Sum of Medians(线段树)[通俗易懂]

Codeforces 85D Sum of Medians(线段树)

大家好,又见面了,我是全栈君。

题目链接:Codeforces 85D – Sum of Medians

题目大意:N个操作,add x:向集合中加入x;del x:删除集合中的x;sum:将集合排序后,将集合中全部下标i % 5 = 3的元素累加求和。

解题思路:线段树单点更新,每一个点维护5个值。分别表示从该段区间中i % 5 = t的和。然后两端区间合并时仅仅须要依据左孩子中元素的个数合并。所以有一个c表示区间上元素的个数。

由于有同样的数。所以要离线操做,将全部的数映射成位置,可是对于del则不须要映射,由于集合中肯定有才干减掉。那么add和sum操作都是能够搞定了,仅仅剩下del操作,对于del x,x肯定在集合中出现过。所以每次删除第一个x就可以,假设高速查找,要借助map和一个辅助数组,由于删除一个后要又一次映射,所以借助辅助数组。

#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;
const int mod = 5;
const int maxn = 1e5+5;

int N, M, pos[maxn], v[maxn];
map<ll, int> G;

#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)|1)
int lc[maxn << 2], rc[maxn << 2], c[maxn << 2];
ll s[maxn << 2][6];

inline void maintain (int u, int d) {
    c[u] += d;
    memset(s[u], 0, sizeof(s[u]));
    s[u][0] = (c[u] ? pos[lc[u]] : 0);
}

inline void pushup(int u) {
    int t = c[lson(u)] % mod;
    c[u] = c[lson(u)] + c[rson(u)];
    for (int i = 0; i < mod; i++)
        s[u][i] = s[lson(u)][i] + s[rson(u)][(i + mod - t) % mod];
}

void build (int u, int l, int r) {
    lc[u] = l;
    rc[u] = r;
    c[u] = 0;
    memset(s[u], 0, sizeof(s[u]));

    if (l == r)
        return;
    int mid = (l + r) / 2;
    build(lson(u), l, mid);
    build(rson(u), mid + 1, r);
    pushup(u);
}

void modify (int u, int x, int d) {
    if (lc[u] == x && rc[u] == x) {
        maintain(u, d);
        return;
    }

    int mid = (lc[u] + rc[u]) / 2;
    if (x <= mid)
        modify(lson(u), x, d);
    else
        modify(rson(u), x, d);
    pushup(u);
}

struct OP {
    int p, k, id;
    OP (int k = 0, int p = 0, int id = 0) {
        this->k = k;
        this->p = p;
        this->id = id;
    }
    friend bool operator < (const OP& a, const OP& b) {
        if (a.k == 0)
            return false;
        if (b.k == 0)
            return true;
        if (a.p != b.p)
            return a.p < b.p;
        return a.id < b.id;
    }
};

inline bool cmp (const OP& a, const OP& b) {
    return a.id < b.id;
}

vector<OP> vec;

void init () {
    scanf("%d", &N);
    char op[5];
    int x;

    for (int i = 1; i <= N; i++) {
        scanf("%s", op);
        if (op[0] == 's')
            vec.push_back(OP(0, 0, i));
        else {
            scanf("%d", &x);
            vec.push_back(OP(op[0] == 'a' ? 1 : -1, x, i));
        }
    }

    M = 1;
    sort(vec.begin(), vec.end());
    for (int i = 0; i < N; i++) {
        if (vec[i].k < 0)
            continue;
        if (vec[i].k == 0)
            break;

        pos[M] = vec[i].p;
        vec[i].p = M++;
    }
    build(1, 1, M);
}

void solve () {
    sort(vec.begin(), vec.end(), cmp);
    for (int i = 0; i < N; i++) {
        //printf("%d %d!\n", vec[i].k, pos[vec[i].p]);
        if (vec[i].k == 0)
            printf("%lld\n", s[1][2]);
        else if (vec[i].k == -1) {
            int tmp = vec[i].p;
            v[G[tmp]] = 0;
            modify(1, G[tmp], -1);

            if (G[tmp] <= N && v[G[tmp]+1] && pos[G[tmp]] == pos[G[tmp]+1])
                G[tmp]++;
            else
                G[tmp] = 0;
        } else {
            int tmp = pos[vec[i].p];
            v[vec[i].p] = 1;
            modify(1, vec[i].p, 1);
            if (G[tmp] == 0)
                G[tmp] = vec[i].p;
        }
    }
}

int main () {
    init();
    solve();
    return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/116117.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ubuntu18.04安装中文输入法_ubuntu搜狗输入法乱码

    ubuntu18.04安装中文输入法_ubuntu搜狗输入法乱码转自:http://blog.csdn.net/u011795345/article/details/53041707最近刚给笔记本装了Ubuntu+win10双系统,但是ubuntu16.04没有自带中文输入法,所以经过网上的一些经验搜索整合,分享一下安装中文输入法的心得。本文主要介绍了谷歌拼音跟ibus中文输入法的安装,由于ibus输入法问题较多,所以目前我用的是谷歌输入法。

    2022年9月26日
    0
  • burpsuite简单抓包教程[通俗易懂]

    burpsuite简单抓包教程[通俗易懂]一.配置浏览器(以火狐为例)1.打开菜单,找到选项,点击翻到最下面点击设置,将配置的代理服务器改为手动代理配置,HTTP代理设为127.0.0.1,端口设置为8080(为了burpsuite能截到浏览器发送出来的请求),点击确定。二.burpsuite的设置点击proxy选择Options观察图中的IP地址及端口,如果不是127.0.0.1:8080,则点击add,添加端口和IP地…

    2022年6月14日
    122
  • J1939入门(一)[通俗易懂]

    J1939入门(一)[通俗易懂]J1939概述SAEJ1939(以下简称J1939)是美国汽车工程协会(SAE)的推荐标准,广泛用于是商用车(重卡、大客车等道路车辆和工程机械、农业机械、轨道机车、船舶等非道路车辆及设备)上电子部件间的数字通讯。

    2022年6月10日
    32
  • 频次最高的38道selenium面试题及答案(下)[通俗易懂]

    频次最高的38道selenium面试题及答案(下)[通俗易懂]20、selenium中隐藏元素定位,你该如何做?隐藏元素可以正常定位到,只是不能操作(定位元素和操作元素是两码事,操作元素是指click、clear、send_keys等这些方法)。我们可以用js来操作隐藏元素。js和selenium不同,只有页面上有的元素(在dom里面的)都能正常操作。21、如何判断一个页面上元素是否存在?法1:用try…except在代码块加上法2:用elements定义组元素方法然后根其元素个数len()<1存在返回True,不存在则返回F.

    2022年6月20日
    21
  • murmurhash算法_shell dash使用数组

    murmurhash算法_shell dash使用数组MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。[1][2][3] 由AustinAppleby在2008年发明,[4][5] 并出现了多个变种,[6] 都已经发布到了公有领域(publicdomain)。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好

    2022年10月19日
    0
  • 傅里叶变换 意义_傅里叶变换表达式

    傅里叶变换 意义_傅里叶变换表达式看到论坛有一个朋友提问为什么傅里叶变换可以将时域变为频域?这个问题真是问到了灵魂深处。在这我只能简单讲讲我的理解,要深刻理解翻信号处理教科书是最好的方法。1.如何描述信号我们常常用数学模型去抽象物理事件。信号也可以用数学模型来表示。有了信号的数学模型,我们就可以利用数学计算对信号模型做各种各样的改变。如果加以计算机,模电,数电的相关知识,我们就可以将我们对信号模型的改变转换为对物理信号的…

    2022年10月20日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号