BZOJ 3262 陌上花开

Description

有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。
现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。
定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。
显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。
 

Input

第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

Output

包含N行,分别表示评级为0...N-1的每级花的数量。

Sample Input

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

Sample Output

3
1
3
0
1
0
1
0
0
1
 
题意  : 三维偏序裸题
代码示例 :
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5+5;
typedef pair<int, int>P;
#define fi first 
#define se second 

int n, m;
struct node
{
	int x, y, z;
	int num, cnt; // num等级 , cnt 数量 
	node(int _x=0, int _y=0, int _z=0):x(_x), y(_y), z(_z){}
	
	bool operator< (const node &v)const{
		if (x == v.x && y == v.y) return z < v.z;
		else if (x == v.x) return y < v.y;
		return x < v.x;
	}
}arr[maxn], f[maxn];
int k = 1;
int c[maxn*2];
int lowbit(int x){return x&(-x); }
void add(int p, int num){
	for(int i = p; i <= m; i += lowbit(i)) c[i] += num; 
}
int query(int p){
	int sum = 0;
	for(int i = p; i ; i -= lowbit(i)){
		sum += c[i];
	}
	return sum;
}

void CDQ(int l, int r){
	if (l == r) return;
	
	int mid = (l+r)>>1;
	CDQ(l, mid);
	CDQ(mid+1, r);
	
	int p1 = l, p2 = mid+1;
	int num = 0;
	for(int i = l; i <= r; i++){
		if (p1<=mid && (p2 > r || arr[p1].y <= arr[p2].y)){
			add(arr[p1].z, arr[p1].cnt);
			f[num++] = arr[p1++];
		}
		else {
			int num2 = query(arr[p2].z);
			arr[p2].num += num2;
			f[num++] = arr[p2++];
		}
	}
	
	num = 0;
	for(int i = l; i <= r; i++) {
		if (i <= mid) add(arr[i].z, -arr[i].cnt);
		arr[i] = f[num++];	
	} 	
}

int ans[maxn];
int main () {
	int x, y, z;
	
	cin >> n >> m;
	for(int i = 1; i <= n; i++){
		scanf("%d%d%d", &x, &y, &z);
		arr[i] = node(x, y, z);
		arr[i].num = arr[i].cnt = 1; 	
	}	
	sort(arr+1, arr+1+n);
		
	for(int i = 2; i <= n; i++){
		if (arr[i].x == arr[k].x && arr[i].y == arr[k].y && arr[i].z == arr[k].z){
			arr[k].num++;
			arr[k].cnt++;
		}
		else arr[++k] = arr[i];
	}	
	CDQ(1, k);
	
	for(int i = 1; i <= k; i++){
		ans[arr[i].num-1] += arr[i].cnt;
	}
	for(int i = 0; i < n; i++) printf("%d\n", ans[i]);
	return 0;
}

 

东北日出西边雨 道是无情却有情
posted @ 2018-08-24 15:50  楼主好菜啊  阅读(115)  评论(0编辑  收藏  举报