• YandexR1 Sum of Medians [线段树]


    Yandex Round1的Sum of Medians题意是这样的,对整数有三种操作,插入,删除和求和,求和的话就是求该序列排序后的mod5==3项的和,然后有两点条件,插入之前,该序列中无该元素,删除之前,该序列中有该元素,然后需要求和的时候要求和。

    这题有两个地方难想,一个是需要离线处理,一个是用线段树来维护。

    先把要使用的整数离散化到[1…n]然后对1…n这个区间建立线段树,维护区间的数字个数及该区间项mod5分别等于0…4的项的和,然后用这两种标记值来递推就可以了,复杂度便是O(NlogN),代码如下:

    #include <iostream>
    #include <string>
    #include <set>
    #include <vector>
    #include <map>
    using namespace std;
     
    const int MAX = 1e5 + 5;
     
    typedef long long int64;
     
    int n, num[MAX];
    int64 cnt[MAX * 10], dp[MAX * 10][5];
    char ch[MAX][5];
    set<int> S;
    map<int, int> m_ii;
    vector<int> val;
     
    void ready()
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%s", ch[i]);
            if(ch[i][0] != 's')
            {
                scanf("%d", &num[i]);
                S.insert(num[i]);
            }
        }
        //离散化
        val = vector<int> (S.begin(), S.end());
        for(int i = 0; i < val.size(); i++)
            m_ii[val[i]] = i;
        
        memset(cnt, 0, sizeof(cnt));
        memset(dp, 0, sizeof(dp));
    }
     
    void update(int u, int L, int R, int x, int d)
    {
        if(L == R)
        {
            cnt[u] += d;
            if(cnt[u])  dp[u][0] = val[x];
            else  dp[u][0] = 0;
            return;
        }
        else
        {
            int M = (L + R) / 2;
            if(x <= M)  update(2 * u + 1, L, M, x, d);
            else  update(2 * u + 2, M + 1, R, x, d);
     
            cnt[u] = cnt[2 * u + 1] + cnt[2 * u + 2];
            
            for(int i = 0; i < 5; i++)
                dp[u][i] = dp[2 * u + 1][i] + dp[2 * u + 2][((i - cnt[2 * u + 1]) % 5 + 5) % 5];
        }
    }
     
    void out(int u, int L, int R)
    {
        printf("cnt[%d] = %d, %d %d %d %d %d\n", u, cnt[u], dp[u][0],
            dp[u][1], dp[u][2], dp[u][3], dp[u][4]);
        if(L == R)  return;
        else
        {
            int M = (L + R) / 2;
            if(L <= M)  out(2 * u + 1, L, M);
            if(M + 1 <= R)  out(2 * u + 2, M + 1, R);
        }
    }
     
    void go()
    {
        for(int i = 0; i < n; i++)
        {
            if(ch[i][0] == 'a')  update(0, 0, val.size() - 1, m_ii[num[i]], 1);
            else if(ch[i][0] == 'd')  update(0, 0, val.size() - 1, m_ii[num[i]], -1);
            else  printf("%I64d\n", dp[0][2]);
        }
        //out(0, 0, val.size() - 1);
    }
     
    int main()
    {
        ready();
        go();
    }
  • 相关阅读:
    082、Java数组之数组传递之简化理解
    081、Java数组之数组传递
    080、Java数组之二维数组的定义及使用
    079、Java数组之数组的静态初始化
    078、Java数组之数组的引用传递
    077、Java数组之分步实现数组操作
    076、Java数组之定义数组
    075、Java面向对象之定义匿名对象
    074、Java面向对象之构造方法重载
    073、Java面向对象之利用构造方法为属性赋值
  • 原文地址:https://www.cnblogs.com/litstrong/p/2085289.html
Copyright © 2020-2023  润新知