HDU 4288 线段树 + 离线处理

来源:互联网 发布:机房网络应急预案 编辑:程序博客网 时间:2024/06/07 23:00

传送门 :HDU 4288

题解

先上代码, 候补

AC code:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;#define mid ((l + r) >> 1)#define ls rt << 1, l, mid#define rs rt << 1 | 1, mid + 1, rtypedef long long LL;const int N = 100000 + 5;int a[N];struct Node {    int len;    LL sum[5];}node[N << 2];struct ch {    int v;//操作数    int f;//f标志操作类型};void pushUp(int rt) {//核心算法, 考察线段树节点意义 : 更新只考虑当前结点和子结点,看做一个小团体     node[rt].len = node[rt << 1].len + node[rt << 1 | 1].len;    for (int i = 0; i < 5; ++i) {//把左孩子当做团体的左端直接给这边sum        node[rt].sum[i] = node[rt << 1].sum[i];    }    for (int i = 0; i < 5; ++i) {//考虑左孩子长        node[rt].sum[(i + node[rt << 1].len) % 5] += node[rt << 1 | 1].sum[i];    }}void update(int rt, int l, int r, int u, int v) {    if (l == r) {        node[rt].sum[1] = v;        node[rt].len += v ? 1 : -1;        return;    }    if (u <= mid) update(ls, u, v);    else update(rs, u, v);    pushUp(rt);}int main() {    //freopen("in.txt", "r", stdin);    int n, v;    char op[10];    ch tmp;    while (cin >> n) {        vector<ch> opv;//存操作        memset(node, 0, sizeof(node));        int nn = 0;        while (n--) {            cin >> op;            if (op[0] == 's')   tmp.f = 0;            else {                cin >> v;                tmp.v = v;                if (op[0] == 'a') {                    tmp.f = 1;                    a[++nn] = v;                }                else tmp.f = -1;            }            opv.push_back(tmp);        }        sort(a + 1, a + nn + 1);//排序离线预处理操作位置        for (int i = 0; i < opv.size(); ++i) {            if (!opv[i].f) cout << node[1].sum[3] << endl;            else {                int pos = upper_bound(a + 1, a + nn + 1, opv[i].v) - a - 1;//二分查找位置                update(1, 1, nn, pos, opv[i].f == 1 ? opv[i].v : 0);//更新            }        }    }    return 0;}
0 0
原创粉丝点击