这是前两天10级排位赛数据结构场的题,当时看了没思路就没去做,这两天在学线段树的时候又想到了这道题,拿来一看这么简单。。。
题意:n个女孩参加舞会,每个女孩有三个属性,如果一个女孩发现有人三项属性都高于自己,她就伤心的跳楼了。。给出n和每个人的属性,问最后有多少人跳楼。
思路:有点类似求逆序数。每个属性的范围是10^9,离散化是必须的了。翅膀先说说自己的做法,其实三个属性都一样的,操作的时候可以任意选取。记三个属性为x、y、z,先按y升序排序,然后给y标号,y相同就标相同的号,标号就是为了离散化~然后按x降序排序,以y为坐标,z为关键字,每次查询区间最大值进行比较、更新即可。可用线段树或树状数组解决。
注意:一个人发现有人比自己强就跳楼了,不要重复统计,不能让人家一直跳楼吧(信春哥,原地满血满状态复活???)
线段树版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/* algorithm : segment tree
Memory 15100K Time 1170MS Language G++
code by : zhyu
*/ #include <cstdio>
#include <cmath>
#include <algorithm>
using
namespace std;
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define FORD(i,h,l) for(int i=(h);i>=(l);--i)
#define N 500010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
int
tree[N<<2]; struct
node { int
x,y,z; }a[N]; bool
cmpy(node a,node b) { return
a.y<b.y; } bool
cmpx(node a,node b) { if (a.x==b.x)
{
if (a.y!=b.y)
return a.y>b.y;
return
a.z>b.z; }
return
a.x>b.x; } void
PushUp( int
rt) { tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
} void
build( int
l, int r, int
rt) { tree[rt]=-1;
if (l==r)
return ;
int
m=(l+r)>>1; build(lson);
build(rson);
} void
update( int
p, int val, int
l, int
r, int rt)
{ if (l==r)
{
tree[rt]=max(tree[rt],val);
return ;
}
int
m=(l+r)>>1; if (p<=m) update(p,val,lson);
else
update(p,val,rson); PushUp(rt);
} int
query( int L, int
R, int
l, int r, int
rt) { if (L>r)
return -1;
if (l>=L && r<=R)
return tree[rt];
int
m=(l+r)>>1; int
res=0; if (L<=m) res=max(res,query(L,R,lson));
if (R>m) res=max(res,query(L,R,rson));
return
res; }; int
main( void )
{ int
n; scanf ( "%d" ,&n);
FOR(i,1,n)
scanf ( "%d" ,&a[i].x);
FOR(i,1,n)
scanf ( "%d" ,&a[i].y);
FOR(i,1,n)
scanf ( "%d" ,&a[i].z);
sort(a+1,a+n+1,cmpy);
int
pre=a[1].y; a[1].y=1;
FOR(i,2,n)
{
int
tmp=a[i].y; if (a[i].y==pre) a[i].y=a[i-1].y;
else
a[i].y=a[i-1].y+1; pre=tmp;
}
int
len=a[n].y; sort(a+1,a+n+1,cmpx);
build(1,len,1);
int
ans=0; int
i=1; while (i<=n)
{
int
j=i; while (j<=n && a[i].x==a[j].x)
{
if (j<=n && query(a[j].y+1,len,1,len,1)>a[j].z) ans++;
j++;
}
j=i;
while (j<=n && a[i].x==a[j].x)
{
update(a[j].y,a[j].z,1,len,1);
j++;
}
i=j;
}
printf ( "%d\n" ,ans);
return
0; } |
树状数组版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
/* algorithm : bit
Memory 9200K Time 920MS Language G++
code by : zhyu
*/ #include <cstdio>
#include <cmath>
#include <algorithm>
using
namespace std;
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define FORD(i,h,l) for(int i=(h);i>=(l);--i)
#define N 500010
#define lowbit(x) (x&(-x))
struct
node { int
x,y,z; }a[N]; int
c[N]; int
n; bool
cmpy(node a,node b) { return
a.y<b.y; } bool
cmpx(node a,node b) { if (a.x==b.x)
{
if (a.y==b.y)
return a.z>b.z;
return
a.y>b.y; }
return
a.x>b.x; } void
update( int
x, int val)
{ while (x>0)
{
if (c[x]<val) c[x]=val;
x-=lowbit(x);
}
} int
getmax( int x)
{ int
res=0; while (x<=n)
{
if (c[x]>res) res=c[x];
x+=lowbit(x);
}
return
res; } int
main( void )
{ scanf ( "%d" ,&n);
FOR(i,1,n)
scanf ( "%d" ,&a[i].x);
FOR(i,1,n)
scanf ( "%d" ,&a[i].y);
FOR(i,1,n)
scanf ( "%d" ,&a[i].z);
sort(a+1,a+n+1,cmpy);
int
pre=a[1].y; a[1].y=1;
FOR(i,2,n)
{
int
tmp=a[i].y; if (a[i].y==pre) a[i].y=a[i-1].y;
else
a[i].y=a[i-1].y+1; pre=tmp;
}
sort(a+1,a+n+1,cmpx);
int
ans=0; int
i=1; while (i<=n)
{
int
j=i; while (j<=n && a[i].x==a[j].x)
{
if (getmax(a[j].y+1)>a[j].z) ans++;
j++;
}
j=i;
while (j<=n && a[i].x==a[j].x)
{
update(a[j].y,a[j].z);
j++;
}
i=j;
}
printf ( "%d\n" ,ans);
return
0; } |