CF - 652 D Nested Segments

题目传送门

题解:

可以将所有线段按照左端点优先小,其次右端点优先大进行排序。

然后对于第 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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/MingSD/p/10422960.html