CF - 652 D Nested Segments
阿新 • • 發佈:2019-02-23
n) hide aps 代碼 print for 接下來 當我 sed
題目傳送門
題解:
可以將所有線段按照左端點優先小,其次右端點優先大進行排序。
然後對於第 i 條線段來說, 那麽第 i+1 ---- n 的線段左端點都一定在第i條線段的右邊, 接下來就需要知道 i+1 ---- n 中的這些線段有多少條的右端點是在第 i 條線段的右端點的左邊。
可以通過一個樹狀數組來維護一個右端點的前綴合。
當我門處理第i條線段的時候, 先將第i條線段的右端點從樹狀數組裏面刪除,然後在詢問在 r 之前有多少個右端點就是相應的答案了。
代碼:
/* code by: zstu wxk time: 2019/02/23 */ #include<bits/stdc++.h> usingView Codenamespace 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] #definemax3(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; booloperator< (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; }
CF - 652 D Nested Segments