3262: 陌上花开
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1423 Solved: 640
[ Submit][ Status][ Discuss]
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
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
1
3
0
1
0
1
0
0
1
HINT
1 <= N <= 100,000, 1 <= K <= 200,000
Source
排序一维
树状数组一维
线段树一维
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 2E5 + 20;
const int T = 100;
struct data{
int a,b,c,Num;
data(){}
data(int a,int b,int c,int Num): a(a),b(b),c(c),Num(Num){}
bool operator < (const data &B) const {
return a < B.a;
}
}f[maxn];
int n,m,cnt,Root[maxn],lc[maxn*T],rc[maxn*T],c[maxn*T],rank[maxn],ans[maxn];
int Getlc(int o) {return lc[o]?lc[o]:lc[o] = ++cnt;}
int Getrc(int o) {return rc[o]?rc[o]:rc[o] = ++cnt;}
int Query(int o,int l,int r,int ql,int qr)
{
if (ql <= l && r <= qr) return c[o];
if (!o) return 0;
int mid = (l + r) >> 1,ret = 0;
if (ql <= mid) ret += Query(lc[o],l,mid,ql,qr);
if (qr > mid) ret += Query(rc[o],mid + 1,r,ql,qr);
return ret;
}
void Insert(int o,int l,int r,int pos)
{
if (l == r) {
++c[o];
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) Insert(Getlc(o),l,mid,pos);
else Insert(Getrc(o),mid + 1,r,pos);
c[o] = c[lc[o]] + c[rc[o]];
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint();
for (int i = 1; i <= n; i++) {
int a,b,c;
a = getint();
b = getint();
c = getint();
f[i] = data(a,b,c,i);
}
sort(f + 1,f + n + 1);
int L = 1;
for (int i = 1; i <= n + 1; i++) {
if (f[i].a != f[i-1].a && i > 1) {
for (int j = L; j < i; j++) {
for (int l = f[j].b; l > 0; l -= l&-l)
rank[f[j].Num] += Query(Root[l],1,m,1,f[j].c);
--rank[f[j].Num];
}
L = i;
}
if (i == n + 1) break;
for (int j = f[i].b; j <= m; j += j&-j) {
if (!Root[j]) Root[j] = ++cnt;
Insert(Root[j],1,m,f[i].c);
}
}
for (int i = 1; i <= n; i++) ++ans[rank[i]];
for (int i = 0; i < n; i++)
printf("%d\n",ans[i]);
return 0;
}