D. Ball
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
N ladies attend the ball in the King's palace. Every lady can be described with three values: beauty, intellect and richness. King's Master of Ceremonies knows that ladies are very special creatures. If some lady understands that there is other lady at the ball which is more beautiful, smarter and more rich, she can jump out of the window. He knows values of all ladies and wants to find out how many probable self-murderers will be on the ball. Lets denote beauty of the i-th lady by Bi, her intellect by Ii and her richness by Ri. Then i-th lady is a probable self-murderer if there is some j-th lady that Bi < Bj, Ii < Ij, Ri < Rj. Find the number of probable self-murderers.
Input
The first line contains one integer N (1 ≤ N ≤ 500000). The second line contains N integer numbers Bi, separated by single spaces. The third and the fourth lines contain sequences Ii and Ri in the same format. It is guaranteed that 0 ≤ Bi, Ii, Ri ≤ 109.
Output
Output the answer to the problem.
Examples
input
Copy
3 1 4 2 4 3 2 2 5 3
output
Copy
1
一、原题地址
二、大致题意
给出n个女士的三位属性xi,yi,zi(注意此处是一行x给完再给y再给z)。若存在xi>xj && yi > yj && zi>zj ,那么第 j 个人就会狗带,也就是说一个人只要存在一个三个属性都严格大于她的人,她就会选择狗带。
询问狗带的人数是多少。
三、大致思路
先将 y 属性离散化,按照离散后的值作为下标建立线段树。接着按照 x 属性从大到小排序,然后依次遍历,这时可以肯定的是当前正在处理到的人她的x值肯定小于之前被更新到线段树里的人的x值。更新线段树时,每更新到一个人 i ,就在她对应的 yi 下标赋值 zi。这样我们在查询一个人 j 是否会狗带时,只需要查询区间[yj+1,Size]的最大值,这个最大值和 zj 进行比较就可以啦。
好巧妙的处理方法呀,相当于人是排队依次进来的,降低了1维后变成二维,再在y的位置上放置这个高度为z的人。
四、代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const LL INF=1e17+10;
int n;
const int maxn=5e5+50;
struct Node
{
int x,y,z;
}a[maxn];
int h[maxn];
struct Tree
{
int l, r, maxx;
};
Tree node[maxn<<2]; //node[maxn]为线段树处理数组
void PushUp(int i)
{
node[i].maxx = max(node[i << 1].maxx, node[(i << 1) | 1].maxx);
}
void build(int i, int l, int r)
{
node[i].l = l; node[i].r = r;
if (l == r)
{
node[i].maxx = 0;
return;
}
int mid = (l + r) / 2;
build(i << 1, l, mid);
build((i << 1) | 1, mid + 1, r);
PushUp (i);
}
int getmax(int i, int l, int r)
{
if (node[i].l == l&&node[i].r == r)
return node[i].maxx;
int mid = (node[i].l + node[i].r) / 2;
if (r <= mid) return getmax(i << 1, l, r);
else if (l>mid) return getmax((i << 1) | 1, l, r);
else return max(getmax(i << 1, l, mid), getmax((i << 1) | 1, mid + 1, r));
}
void add(int i, int k, int v)
{
if (node[i].l == k&&node[i].r == k)
{
node[i].maxx = max(node[i].maxx,v);
return;
}
int mid = (node[i].l + node[i].r) / 2;
if (k <= mid) add(i << 1, k, v);
else add((i << 1) | 1, k, v);
PushUp (i);
}
bool cmp(Node xx,Node yy)
{
if(xx.x!=yy.x)return xx.x>yy.x;
else if(xx.y!=yy.y)return xx.y>yy.y;
else return xx.z>yy.z;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i].x);
for(int i=1;i<=n;i++)scanf("%d",&a[i].y),h[i]=a[i].y;
for(int i=1;i<=n;i++)scanf("%d",&a[i].z);
sort(h+1,h+1+n);
int Size=unique(h+1,h+1+n)-h-1;
build(1,1,Size+1);
sort(a+1,a+1+n,cmp);
int preval=a[1].x;
int prei,ans=0;
//printf("----------\n");
for(int i=1;i<=n;)
{
prei=i;
for(;a[i].x==a[prei].x&&i<=n;i++)
{
//printf("%d %d %d\n",a[i].x,a[i].y,a[i].z);
a[i].y=lower_bound(h+1,h+1+Size,a[i].y)-h;
//printf("%d %d\n",a[i].y+1,Size+1);
if(getmax(1,a[i].y+1,Size+1)>a[i].z)ans++;
}
for(;prei<i;prei++)
{
add(1,a[prei].y,a[prei].z);
}
}
printf("%d\n",ans);
}