【Educational Codeforces Round 10D】【树状数组】Nested Segments 每条线段内部有多少条线段

来源:互联网 发布:软件架构 pdf 编辑:程序博客网 时间:2024/05/12 09:43
D. Nested Segments
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given n segments on a line. There are no ends of some segments that coincide. For each segment find the number of segments it contains.

Input

The first line contains a single integer n (1 ≤ n ≤ 2·105) — the number of segments on a line.

Each of the next n lines contains two integers li and ri ( - 109 ≤ li < ri ≤ 109) — the coordinates of the left and the right ends of the i-th segment. It is guaranteed that there are no ends of some segments that coincide.

Output

Print n lines. The j-th of them should contain the only integer aj — the number of segments contained in the j-th segment.

Examples
input
41 82 34 75 6
output
3010
input
33 41 52 6
output
011



#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<ctype.h>#include<math.h>#include<set>#include<map>#include<vector>#include<queue>#include<bitset>#include<algorithm>#include<time.h>using namespace std;void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }const int N = 2e5 + 10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;int n;int b[N + N];int l[N], r[N];map<int, int>mop;map<int, int>::iterator it;struct A{int x, y, o;bool operator < (const A& b)const{if (x != b.x)return x < b.x;return y < b.y;}}a[N];int id;void add(int x, int val){for (x; x <= id; x += (x&-x)){b[x] += val;}}int check(int x){int tmp = 0;for (; x; x -= (x&-x)){tmp += b[x];}return tmp;}int ans[N];int main(){while (~scanf("%d", &n)){mop.clear();for (int i = 1; i <= n; ++i){scanf("%d%d", &l[i], &r[i]);mop[l[i]] = 0;mop[r[i]] = 0;}id = 0;for (it = mop.begin(); it != mop.end(); ++it){it->second = ++id;b[id] = 0;}for (int i = 1; i <= n; ++i){int x = mop[l[i]];int y = mop[r[i]];a[i].x = x;a[i].y = y;a[i].o = i;add(y, 1);}sort(a + 1, a + n + 1);int p = 1;for (int i = 1; i <= n; ++i){while (p <= n&&a[p].x < a[i].x){add(a[p].y, -1);++p;}ans[a[p].o] = check(a[p].y) - 1;}for (int i = 1; i <= n; ++i)printf("%d\n", ans[i]);}return 0;}/*【题意】有n(2e5)条线段共线,端点范围在[-1e9,1e9]告诉你每条线段的端点坐标(没有两条线段共端点)问你每条线段内部有多少条线段【类型】树状数组【分析】我们可以先按线段的左端点排序。把比当前左端点小的线段扔掉。直接用树状数组计数右端点<=当前右端点的线段个数。【时间复杂度&&优化】O(nlogn)*/


0 0
原创粉丝点击