zoukankan      html  css  js  c++  java
  • Yandex.Algorithm 2011 Round 1 D. Sum of Medians 线段树

    题目链接:

    Sum of Medians

    Time Limit:3000MS
    Memory Limit:262144KB
    #### 问题描述 > In one well-known algorithm of finding the k-th order statistics we should divide all elements into groups of five consecutive elements and find the median of each five. A median is called the middle element of a sorted array (it's the third largest element for a group of five). To increase the algorithm's performance speed on a modern video card, you should be able to find a sum of medians in each five of the array. > > A sum of medians of a sorted k-element set S = {a1, a2, ..., ak}, where a1 < a2 < a3 < ... < ak, will be understood by as > > > The operator stands for taking the remainder, that is stands for the remainder of dividing x by y. > > To organize exercise testing quickly calculating the sum of medians for a changing set was needed. #### 输入 > The first line contains number n (1 ≤ n ≤ 105), the number of operations performed. > > Then each of n lines contains the description of one of the three operations: > > add x — add the element x to the set; > del x — delete the element x from the set; > sum — find the sum of medians of the set. > For any add x operation it is true that the element x is not included in the set directly before the operation. > > For any del x operation it is true that the element x is included in the set directly before the operation. > > All the numbers in the input are positive integers, not exceeding 109. #### 输出 > For each operation sum print on the single line the sum of medians of the current set. If the set is empty, print 0. > > Please, do not use the %lld specificator to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams (also you may use the %I64d specificator). #### 样例 > **sample input** > 14 > add 1 > add 7 > add 2 > add 5 > sum > add 6 > add 8 > add 9 > add 3 > add 4 > add 10 > sum > del 1 > sum > > **sample output** > 5 > 11 > 13

    题意

    求当前有序集合中所有下标%5==3的数字的和。

    题解

    对于一个区间,我们可以维护相对的%5=x的位置,比如对于区间[a,a],那它%5为1的数为val[a],其他的都为0,这样我们在合并的时候左边的%5==x的位置是不会变的,右边的只要看左边有多少个数就知道要用x’(偏移)取和x合并了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define M l+(r-l)/2
    using namespace std;
    
    const int maxn = 1e5 + 10;
    typedef __int64 LL;
    
    LL sumv[maxn << 2][5];
    int cntv[maxn << 2];
    int n;
    char cmd[maxn][11];
    int val[maxn];
    vector<int> ha;
    
    void maintain(int o) {
    	cntv[o] = cntv[lson] + cntv[rson];
    	for (int i = 0; i < 5; i++) {
    		sumv[o][i] = sumv[lson][i] + sumv[rson][((i - cntv[lson]) % 5 + 5) % 5];
    	}
    }
    
    int _p,_type;
    void update(int o, int l, int r) {
    	if (l==r) {
    		if (_type =='d') {
    			sumv[o][1] = 0;
    			cntv[o] = 0;
    		}
    		else {
    			sumv[o][1] = ha[l - 1];
    			//printf("(%d,%d):%d", l);
    			cntv[o] = 1;
    		}
    	}
    	else {
    		if (_p <= M) update(lson, l, M);
    		else update(rson, M + 1, r);
    		maintain(o);
    	}
    }
    
    int main() {
    	scanf("%d", &n);
    	memset(sumv, 0, sizeof(sumv));
    	memset(cntv, 0, sizeof(cntv));
    	for (int i = 0; i < n; i++) {
    		scanf("%s", cmd[i]);
    		if (cmd[i][0] != 's') {
    			scanf("%d", &val[i]);
    			ha.push_back(val[i]);
    		}
    	}
    	sort(ha.begin(), ha.end());
    	ha.erase(unique(ha.begin(), ha.end()),ha.end());
    	for (int i = 0; i < n; i++) {
    		if (cmd[i][0] !='s') {
    			_p = lower_bound(ha.begin(), ha.end(), val[i]) - ha.begin() + 1;
    			_type = cmd[i][0];
    			update(1, 1, n);
    		}
    		else {
    			printf("%I64d
    ", sumv[1][3]);
    		}
    	}
    	return 0;
    }
    

    乱起八糟

    线段树是递归的思想,所以它区间保存的数据不能是绝对的!只能是相对的!是只对当前这个区间定义的!而不是对整个区间定义的!所以,如果你想用子节点来表示在全局中%5是什么情况,可能就会比较麻烦了吧。

  • 相关阅读:
    03.redis集群
    02.redis数据同步
    01.redis数据类型
    06.MySQL主从同步
    05.MySQL优化
    04.MySQL慢查询
    lamp服务器站点目录被植入广告代码
    tar命令简单用法
    linux基础优化
    Linux 思想与法则
  • 原文地址:https://www.cnblogs.com/fenice/p/5687503.html
Copyright © 2011-2022 走看看