CF12D Ball

用树状数组也能写

Idea

对于女人\(i\),想要知道她自不自杀,无非是有没有女人\(j\),使得\(B_i<B_j\&\&I_i<I_j\&\&R_i<R_j\)。这里用树状数组表示前\(i\)个女人中\(R\)值的最大值写,由于那三个值小于等于\(1e9\),所以必须离散化。相对其中某个量(这里我按\(B\)来排序)升序排序,然后编号,这样生成的树状数组,保证在查询时满足\(getmax(id+1)\)中所有的女人的\(B\)值比当前女人的要大。于是再按\(I\)值降序,这样保证在之后的遍历中,\(lady[i].i\ge lady[i-1].i\),再以\(R\)值更新树状数组

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<string>
#define ll long long
#define maxn 500050
#define inf 2147483647
#define mod 10003
#define eps 1e-6
#define pi acos(-1.0)
#define de(x) ((x)*(x))
using namespace std; 
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int c[maxn],cnt,n,ans;
struct Node{
    int b,i,r,id;
}a[maxn];
inline void add(int x,int d){
    while(x>0){
        if(c[x]<d) c[x]=d;
        x-=x&(-x);
    }
}
inline int getmax(int x){
    int res=-1;
    for(int i=x;i<=cnt;i+=i&(-i))
        if(res<c[i]) res=c[i];
    return res;
}
inline bool cmp(Node a,Node b){return a.b<b.b;}
inline bool cmp1(Node a,Node b){return a.i>b.i;}
signed main(){
    n=read();
    int i,j;
    for(i=0;i<n;i++) a[i].b=read();
    for(i=0;i<n;i++) a[i].i=read();
    for(i=0;i<n;i++) a[i].r=read();
    sort(a,a+n,cmp); cnt=1; a[0].id=1;
    for(i=1;i<n;i++)
        if(a[i].b==a[i-1].b) a[i].id=cnt;
        else a[i].id=++cnt;//这个地方不能写成cnt++;原因您们懂得
    sort(a,a+n,cmp1);
    for(i=1;i<=cnt;i++) c[i]=-1;
    for(i=0;i<n;){
        for(j=i;j<n&&a[i].i==a[j].i;j++)
            if(getmax(a[j].id+1)>a[j].r) ans++;
        for(j=i;j<n&&a[i].i==a[j].i;j++)
            add(a[j].id,a[j].r);
        i=j; 
    }
    printf("%d",ans);
    return 0;
}
上一篇:CF12D Ball(cdq)


下一篇:web前端入门到实战:CSS3 创建简单的网页动画 – 实现弹跳球动