【树状数组】HDU 5372 Segment Game

通道

题意:加线段,删线段,每次加线段询问当前线段完整覆盖了多少条线段

思路:对于新插入的线段,查询有多少个线段左端点大于等于该线段的左端点。 再查询有多少个线段的右端点大于该线段右端点, 两者之差就是答案。用两个树状数组搞定。

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c = getchar() , c == EOF) return false;
    while(c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return true;
}

typedef long long ll;

const int MAX_N = 900007;

int n;
ll bit[MAX_N][2];

int sum(int i, int id) {
    int s = 0;
    while (i > 0) {
        s += bit[i][id];
        i -= i & -i;
    }
    return s;
}

int up;
void add(int i, int x, int id) {
    while (i <= up) {
        bit[i][id] += x;
        i += i & -i;
    }
}

struct Query {
    int t, l, r;
    Query() {
        
    }
    Query(int _t, int _l, int _r) {
        t = _t; l = _l; r = _r;
    }
};

int id[MAX_N];
bool vis[MAX_N];
Query Q[MAX_N];
vector<ll> a;

int main() {
    int cas = 0;
    while (1 == scanf("%d", &n)) {
        memset(bit, 0, sizeof bit);
        memset(vis, false, sizeof vis);
        a.clear();
        int dec = 0, cnt = 0, Z = 1;
        for (int i = 1; i <= n; ++i) {
            rd(Q[i].t), rd(Q[i].l);
            if (Q[i].t == 0) {
                id[Z++] = i;
                Q[i].r = Q[i].l + i - dec;
                a.push_back(Q[i].l), a.push_back(Q[i].r);
            } else  ++dec;
        }
        sort(a.begin(),a.end()); 
        vector<ll>::iterator iter = unique(a.begin(), a.end()); 
        a.erase(iter,a.end()); 
        printf("Case #%d:\n", ++cas);
        up = a.size();
        for (int i = 1; i <= n; ++i) {
            if (Q[i].t == 0) {
                int l = (lower_bound(a.begin(), a.end(), Q[i].l) - a.begin()) + 1;
                int r = (lower_bound(a.begin(), a.end(), Q[i].r) - a.begin()) + 1;
                int ans = sum(up, 0) - sum(l - 1, 0) - sum(up, 1) + sum(r, 1);
                printf("%d\n", ans); 
                vis[i] = true;
                add(l, 1, 0); add(r, 1, 1);
            } else {
                int vl = id[Q[i].l];
                int l = (lower_bound(a.begin(), a.end(), Q[vl].l) - a.begin()) + 1;
                int r = (lower_bound(a.begin(), a.end(), Q[vl].r) - a.begin()) + 1;
                if (vis[vl]) {
                    add(l, -1, 0); add(r, -1, 1);
                } 
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2015-08-11 19:21  mithrilhan  阅读(149)  评论(0编辑  收藏  举报