codeforces 652D . Nested Segments 线段树

时间:2023-12-24 08:04:49

题目链接

我们将线段按照右端点从小到大排序, 如果相同, 那么按照左端点从大到小排序。

然后对每一个l, 查询之前有多少个l比他大, 答案就是多少。因为之前的r都是比自己的r小的, 如果l还比自己大的话, 那么自己就可以包含它。 记得离散化。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <complex>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef complex <double> cmx;
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
struct node
{ int l, r, id;
bool operator < (node a) const
{
if(r == a.r)
return l>a.l;
return r<a.r;
}
}q[200005];
int b[200005], ans[200005], sum[200005<<2];
void update(int p, int l, int r, int rt) {
if(l == r) {
sum[rt] ++;
return ;
}
int m = l+r>>1;
if(p<=m)
update(p, lson);
else
update(p, rson);
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
int query(int L, int R, int l, int r, int rt){
if(L<=l&&R>=r){
return sum[rt];
}
int m = l+r>>1, ret = 0;
if(L<=m)
ret += query(L, R, lson);
if(R>m)
ret += query(L, R, rson);
return ret;
}
int main()
{
int n;
cin>>n;
for(int i = 0; i < n; i++) { scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
b[i] = q[i].l;
}
sort(q, q+n);
sort(b, b+n);
for(int i = 0; i < n; i++) {
int x = lower_bound(b, b+n, q[i].l)-b+1;
ans[q[i].id] = query(x, n, 1, n, 1);
update(x, 1, n, 1);
}
for(int i = 0; i<n; i++) {
printf("%d\n", ans[i]);
}
return 0;
}