HDU-4288 Coder 线段树

通过离线处理,由于线段树不能够动态的扩张,将所有的数都进行永久标号,无视信息的冗余。对于每一个节点,保留对5取余的所有余数的和值,用long long存储。然后根据元素个数进行更新。

代码如下:

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<set>

#include<map>

#include<cstring>

#include<vector>

#include<string>

#define MAXN 100005

using namespace std;



typedef long long Int64;



char op[MAXN][5];

int num[MAXN], rec[MAXN], idx;



map<int,int>mp;



struct Node {

    int l, r, tot;

    Int64 a[5];

}s[MAXN*4];



void build(int p, int l, int r) {

    s[p].l = l, s[p].r = r,    s[p].tot = 0;

    memset(s[p].a, 0, sizeof (s[p].a));

    if (l != r) {

        int mid = (l + r) >> 1;

        build(p<<1, l, mid);

        build(p<<1|1, mid+1, r);

    }

}



void push_up(int p) {

    s[p].tot = s[p<<1].tot + s[p<<1|1].tot;

    for (int i = 0; i < 5; ++i) {

        int k = (s[p<<1].tot+i) % 5;

        s[p].a[k] = s[p<<1].a[k] + s[p<<1|1].a[i];

    }

}



void modify(int p, int pos, int f) {

    if (s[p].l == s[p].r) {

        if (f > 0) { 

            s[p].tot = 1, s[p].a[1] = rec[pos-1];

            // rec[pos-1]保留的是原来的值

        } else {

            s[p].tot = 0; s[p].a[1] = 0;

        }

    } else {

        int mid = (s[p].l + s[p].r) >> 1;

        if (pos <= mid) {

            modify(p<<1, pos, f);

        } else {

            modify(p<<1|1, pos, f);

        }

        push_up(p);

    }

}



int main()

{

    int N;

    while (scanf("%d", &N) != EOF) {

        idx = -1;

        mp.clear();

        for (int i = 1; i <= N; ++i) {

            scanf("%s", op[i]);

            if (op[i][0] == 'a') {

                scanf("%d", &num[i]);

                rec[++idx] = num[i];

            } else if (op[i][0] == 'd') {

                scanf("%d", &num[i]);

                rec[++idx] = num[i];

            }

        }

        sort(rec, rec+idx+1);

        idx = unique(rec, rec+idx+1) - rec; // 返回的是元素个数 

        for (int i = 0; i < idx; ++i) {

            mp[rec[i]] = i + 1; // 对数字进行离散化  

        }

        if (idx != -1) {

            build(1, 1, idx);

        }

        for (int i = 1; i <= N; ++i) {

            if (op[i][0] == 'a') {

                modify(1, mp[num[i]], 1);

            } else if (op[i][0] == 'd'){

                modify(1, mp[num[i]], -1);

            } else {

                printf("%I64d\n", s[1].a[3]);

            }

        }

    }

    return 0;

}

你可能感兴趣的:(code)