hdu 4288 Coder(树形结构-线段树)

<span style="font-family: 'Times New Roman'; font-size: 12px;">Coder</span>

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3187    Accepted Submission(s): 1258

Problem Description

  In mathematics and computer science, an algorithm describes a set of procedures or instructions that define a procedure. The term has become increasing popular since the advent of cheap and reliable computers. Many companies now employ a single coder to write
an algorithm that will replace many other employees. An added benefit to the employer is that the coder will also become redundant once their work is done. 1

  You are now the signle coder, and have been assigned a new task writing code, since your boss would like to replace many other employees (and you when you become redundant once your task is complete).

Your code should be able to complete a task to replace these employees who do nothing all day but eating: make the digest sum.

  By saying “digest sum” we study some properties of data. For the sake of simplicity, our data is a set of integers. Your code should give response to following operations:

  1. add x – add the element x to the set;

  2. del x – remove the element x from the set;

  3. sum – find the digest sum of the set. The digest sum should be understood by

  where the set S is written as {a1, a2, ... , ak} satisfying a1 < a2 < a3 < ... < ak

  Can you complete this task (and be then fired)?

------------------------------------------------------------------------------

1 See http://uncyclopedia.wikia.com/wiki/Algorithm

Input

  There’re several test cases.

  In each test case, the first line contains one integer N ( 1 <= N <= 105 ), the number of operations to process.

  Then following is n lines, each one containing one of three operations: “add x” or “del x” or “sum”.

  You may assume that 1 <= x <= 109.

  Please see the sample for detailed format.

  For any “add x” it is guaranteed that x is not currently in the set just before this operation.

  For any “del x” it is guaranteed that x must currently be in the set just before this operation.

  Please process until EOF (End Of File).

Output

  For each operation “sum” please print one line containing exactly one integer denoting the digest sum of the current set. Print 0 if the set is empty.

Sample Input

9
add 1
add 2
add 3
add 4
add 5
sum
add 6
del 3
sum
6
add 1
add 3
add 5
add 7
add 9
sum

Sample Output

3
4
5

Hint

C++ maybe run faster than G++ in this problem.

这题线段树有点分治的感觉,下面举个例子就明白了,看图:


#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
using namespace std;

#define ll long long
const int maxn = 100010;
struct tree{
    int l , r , sum;
    ll mod[5];
}a[4*maxn];
struct OP{
    char op;
    int x;
    OP(char o = 'a' , int a = 0){
        op = o , x = a;
    }
};
int N , cnt , value[maxn];
map<int , int> mp;
vector<OP> operate;

void pushup(int k){
    a[k].sum = a[2*k].sum+a[2*k+1].sum;
    int x = a[2*k].sum%5;
    for(int i = 0; i < 5; i++){
        a[k].mod[(x+i)%5] = a[2*k].mod[(x+i)%5]+a[2*k+1].mod[i];
    }
}

void build(int l , int r , int k){
    a[k].l = l;
    a[k].r = r;
    a[k].sum = 0;
    for(int i = 0; i < 5; i++) a[k].mod[i] = 0;
    if(l != r){
        int mid = (l+r)/2;
        build(l ,mid , 2*k);
        build(mid+1 , r , 2*k+1);
    }
}

void update(int l , int r , int k , int c){
    if(l <= a[k].l && a[k].r <= r){
        if(c < 0) a[k].sum -= 1;
        else a[k].sum += 1;
        a[k].mod[1] += c;
    }else{
        int mid = (a[k].l+a[k].r)/2;
        if(mid >= r) update(l , r , 2*k , c);
        else update(l , r , 2*k+1 , c);
        pushup(k);
    }
}

void initial(){
    mp.clear();
    cnt = 0;
    operate.clear();
}

void readcase(){
    char op[10];
    int x;
    for(int i = 0; i < N; i++){
        scanf("%s" , op);
        if(op[0] == 'a' || op[0] == 'd'){
            scanf("%d" , &x);
            operate.push_back(OP(op[0] , x));
            mp[x] = 0;
        }else operate.push_back(OP(op[0] , -1));
    }
    for(map<int , int>::iterator it = mp.begin(); it != mp.end(); it++){
        it->second = cnt;
        value[cnt++] = it->first;
    }
}

void computing(){
    build(0 , cnt-1 , 1);
    for(int i = 0; i < N; i++){
        char op = operate[i].op;
        int x = operate[i].x;
        if(op == 'a') update(mp[x] , mp[x] , 1 , x);
        else if(op == 'd') update(mp[x] , mp[x] , 1 , -1*x);
        else{
            printf("%I64d\n" , a[1].mod[3]);
        }
    }
}

int main(){
    while(~scanf("%d" , &N)){
        initial();
        readcase();
        computing();
    }
    return 0;
}
时间: 2024-10-10 05:39:30

hdu 4288 Coder(树形结构-线段树)的相关文章

hdu 4267 A Simple Problem with Integers(树形结构-线段树)

A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3708    Accepted Submission(s): 1139 Problem Description Let A1, A2, ... , AN be N elements. You need to deal with

hdu 1754 I Hate It 线段树 点修改

// hdu 1754 I Hate It 线段树 点修改 // // 不多说,裸的点修改 // // 继续练 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #i

HDU 4902 Nice boat(线段树 区间更新)

Nice boat 大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x  2:把区间中大于x的数变成gcd(a[i], x),最后输出序列. 思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用. 1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8

hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor

hdu 2852 KiKi&#39;s K-Number (线段树)

hdu 2852 题意: 一个容器,三种操作: (1) 加入一个数 e (2) 删除一个数 e,如果不存在则输出 No Elment! (3) 查询比a大的数中的第k小数,不存在就输出 Not Find! 解法: 关于第三点,可以先查询小于等于a的数的个数cnt,然后直接查询第cnt+k小数就行了 . 二分+树状数组 或者 主席树(有点杀鸡用牛刀的感觉 ...) 也是可以做的  _(:з」∠)_ code:线段树 1 #include <iostream> 2 #include <cst

Bestcoder round #65 &amp;&amp; hdu 5592 ZYB&#39;s Premutation 线段树

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 74 Problem Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutat

hdu 1166 敌兵布阵 线段树 点更新

// hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就可以了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 虽然十分简单,十分的水,继续加油 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits

HDU 1698 Just a Hook (线段树,区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17214    Accepted Submission(s): 8600 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

HDU 4107 Gangster Segment Tree线段树

这道题也有点新意,就是需要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提高速度的目的. 本题过的人很少,因为大部分都超时了,我严格按照线段树的方法去写,一开始居然也超时. 然后修补了两个地方就过了,具体修改的地方请参看程序. 知道最大值段和最小值段,然后修补一下就能过了.不是特别难的题目. #include <stdio.h> #include <string> #include <algorithm> using namespace std; c