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;
}
posted @ 2019-09-05 09:45  云山乱  阅读(194)  评论(0编辑  收藏  举报