http://acm.hdu.edu.cn/showproblem.php?pid=5372
/* 要求有多少线段被现在加进去的线段完全覆盖,所求即左端点比当前加进去的线段大的减去右端点比当前加进去的线段大的,就是覆盖的线段树 用两个树状数组来更新左端点和右端点的值 跟求逆序数那道题目一样,进行排序,二分得到现在排序之后的位置,因为前面加进去的能更新后面的 */ /************************************************ * Author :Powatr * Created Time :2015-8-14 14:15:49 * File Name :1004.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int MAXN = 5e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int b[MAXN][3]; int id[MAXN]; int C1[MAXN], C2[MAXN]; int a[MAXN]; int m; int getid(int x) { return lower_bound(a, a + m, x) - a + 1;//使得从1开始 } void add(int *tr, int x, int k) { while(x <= m){ tr[x] += k; x += x&-x; } } int query(int *tr, int x) { int ret = 0; while( x > 0){ ret += tr[x]; x -= x&-x; } return ret; } int main() { int n; int cout = 0; while(~scanf("%d", &n)){ printf("Case #%d: ", ++cout); m = 0; int cout1 = 0; for(int i = 1; i <= n; i++){ scanf("%d%d", &b[i][0], &b[i][1]); if(b[i][0] == 0){ id[++cout1] = i; b[i][2] = b[i][1] + cout1; a[m++] = b[i][1]; a[m++] = b[i][2]; } } sort(a, a + m); int l, r; m = unique(a, a + m) - a; memset(C1, 0, sizeof(C1)); memset(C2, 0, sizeof(C2)); for(int i = 1; i <= n; i++){ if(b[i][0] == 0){ l = getid(b[i][1]); r = getid(b[i][2]); printf("%d ", query(C2, r) - query(C1, l-1)); add(C1, l, 1); add(C2, r, 1); } else { int p = id[b[i][1]]; l = getid(b[p][1]); r = getid(b[p][2]); add(C1, l, -1); add(C2, r, -1); } } } return 0; }