现在的位置: 首页 > 综合 > 正文

Codeforces 12D. Ball(线段树&多维排序)

2019年04月12日 ⁄ 综合 ⁄ 共 2590字 ⁄ 字号 评论关闭

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.

Sample test(s)
input
3
1 4 2
4 3 2
2 5 3
output
1

题意:

N (1 ≤ N ≤ 500000)个女士去参加舞会。每个女士有三个值ai,bi,ci。如果女士i发现有其它女士的这三个值都比自己高的话就会去跳楼--||.现在问你最后会有多少跳楼的女士。

思路:

以前没做过这样的线段树。其实还是蛮有意思的。先按a大的在前面排序如果这样我们就可以保证。只有排在前面的女士才可能逼死排在后面的女士。现在要解决的就是怎么判断一个女士会不会自杀了。我们可以将b离散化。用一颗线段树维护在b值为b时c的最大值。我们就可以查询b值大于b时c值的最大值。然后我们按排序的顺序将每个女士加进线段树。要注意的是a值相同的必须先计算完在加进线段树。以为必须保证线段树里的女士的a值都比现在大。这样就可以判断了。

详细见代码:

#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=500100;
typedef long long ll;
#define lson L,mid,ls
#define rson mid+1,R,rs
int mav[maxn<<2],H[maxn],m,n;
struct node
{
    int x,y,z;
} wo[maxn];
bool cmp(node a,node b)
{
    return a.y>b.y;
}
void build(int L,int R,int rt)
{
    mav[rt]=0;
    if(L==R)
        return ;
    int ls=rt<<1,rs=ls|1,mid=(L+R)>>1;
    build(lson);
    build(rson);
}
void update(int L,int R,int rt,int p,int v)
{
    if(L==R)
    {
        mav[rt]=max(mav[rt],v);
        return;
    }
    int ls=rt<<1,rs=ls|1,mid=(L+R)>>1;
    if(p<=mid)
        update(lson,p,v);
    else
        update(rson,p,v);
    mav[rt]=max(mav[ls],mav[rs]);
}
int qu(int L,int R,int rt,int l,int r)
{
    if(l<=L&&R<=r)
        return mav[rt];
    int ls=rt<<1,rs=ls|1,mid=(L+R)>>1,val=0;
    if(l<=mid)
        val=max(val,qu(lson,l,r));
    if(r>mid)
        val=max(val,qu(rson,l,r));
    return val;
}
void init()
{
    sort(H,H+m);
    m=unique(H,H+m)-H;
    build(1,m,1);
    for(int i=0;i<n;i++)
        wo[i].x=lower_bound(H,H+m,wo[i].x)-H+1;
    sort(wo,wo+n,cmp);
}
int main()
{
    int i,j,k,ans;

    while(~scanf("%d",&n))
    {
        for(i=0;i<n;i++)
        {
            scanf("%d",&wo[i].x);
            H[i]=wo[i].x;
        }
        for(i=0;i<n;i++)
            scanf("%d",&wo[i].y);
        for(i=0;i<n;i++)
            scanf("%d",&wo[i].z);
        m=n,ans=0;
        init();
        for(i=0;i<n;i=j)//y从小到大保证线段树中的y都比当前y大。
        {
            j=i;
            while(j<n&&wo[j].y==wo[i].y)
            {
                if(qu(1,m,1,wo[j].x+1,m)>wo[j].z)
                    ans++;
                j++;
            }
            for(k=i;k<j;k++)
                update(1,m,1,wo[k].x,wo[k].z);//线段树维护值为x范围[L,R]间z的最大值
        }
        printf("%d\n",ans);
    }
    return 0;
}

抱歉!评论已关闭.