题解:
可以将所有线段按照左端点优先小,其次右端点优先大进行排序。
然后对于第 i 条线段来说, 那么第 i+1 ---- n 的线段左端点都一定在第i条线段的右边, 接下来就需要知道 i+1 ---- n 中的这些线段有多少条的右端点是在第 i 条线段的右端点的左边。
可以通过一个树状数组来维护一个右端点的前缀合。
当我门处理第i条线段的时候, 先将第i条线段的右端点从树状数组里面删除,然后在询问在 r 之前有多少个右端点就是相应的答案了。
代码:
/* code by: zstu wxk time: 2019/02/23 */ #include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 5e5 + 100; struct Node{ int l, r, id; bool operator< (const Node & x) const{ if(l == x.l) return r > x.r; return l < x.l; } }A[N]; int b[N]; int k = 0, n; int F(int x){ return lower_bound(b+1, b+1+k, x) - b; } int tree[N]; void Updata(int x, int c){ while(x <= k){ tree[x] += c; x += x & (-x); } return ; } int Query(int x){ int ret = 0; while(x > 0){ ret += tree[x]; x -= x & (-x); } return ret; } int ans[N]; void Ac(){ for(int i = 1; i <= n; ++i){ scanf("%d%d", &A[i].l, &A[i].r); A[i].id = i; b[++k] = A[i].l; b[++k] = A[i].r; } sort(A+1, A+1+n); sort(b+1, b+1+k); k = unique(b+1, b+1+k) - (b+1); for(int i = 1; i <= n; ++i) Updata(F(A[i].r), 1); for(int i = 1; i <= n; ++i){ Updata(F(A[i].r), -1); ans[A[i].id] = Query(F(A[i].r)); } for(int i = 1; i <= n; ++i) printf("%d\n", ans[i]); } int main(){ while(~scanf("%d", &n)){ Ac(); } return 0; }