您的位置:首页 > 其它

CF 12D BALL 线段树 && 树状数组

2012-05-12 20:05 246 查看
http://codeforces.com/problemset/problem/12/D

线段树

View Code

/*
CF  12D
树状数组好题
给你n个整数三元组,
对于某个三元组,判断是否存在一个三元组的元素都大于这个三元组
题目给三个数,必然有其道理
可以把其中一个数离散化当做树状数组的下标,再按照另外某个数排序
最后就只需利用树状数组数组处理好最后一个数就行了

具体做法:
比如对x离散化   对y降序排序
x当做树状数组的下标
每次把y值相同的三元组一起拿出来处理
因为前面加进树状数组的数的y值肯定比现在这个数的y值要大,这一个数就不必考虑了
然后就是找前面加进树状数组的数中有没有z坐标 大于 当前枚举的数的z坐标,当然是在大于x的区间内
这里与树状数组的功能相反了,这里树状数组是求前n项中的最大值,而题目要求下标在x->n间的最大值
转换一下就好了
离散化前:1 3 5 7 9
离散化后并不是1 2 3 4 5
要倒过来:5 4 3 2 1
那么小于x的区间实际上就是大于x的区间
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 500010;
int c
;
int num
;
int n;
struct node{
int x,y,z;
}in
;
inline void Max(int &a,int b){
if(a<b) a=b;
}
void update(int x,int d){
for(;x<N;x+=x&-x)    Max(c[x],d);
}
int sum(int x){
int ans=0;
for(;x>0;x-=x&-x)    Max(ans,c[x]);
return ans;
}
void init(){
sort(num+1,num+n+1);
int tot=unique(num+1,num+n+1)-num-1;
for(int i=1;i<=n;i++)
in[i].x=tot-(lower_bound(num+1,num+1+tot,in[i].x)-num-1);
//把x的相对大小倒了过来  所以小于in[i].x实际表示大于in[i].x;,便于树状数组的sum操作
}
inline int cmp(node a,node b){
return a.y>b.y;
}
int main()
{
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++) {scanf("%d",&in[i].x);    num[i]=in[i].x;}
for(i=1;i<=n;i++) scanf("%d",&in[i].y);
for(i=1;i<=n;i++) scanf("%d",&in[i].z);
init();
memset(c,0,sizeof(c));
sort(in+1,in+n+1,cmp);
int ans=0;
for(i=1;i<=n;i=j){
for(j=i;j<=n&&in[j].y==in[i].y;j++){
int z=sum(in[j].x-1);
if(z>in[j].z) ans++;
}
for(;i<=j-1;i++)
update(in[i].x,in[i].z);
}
printf("%d\n",ans);
return 0;
}
/*
3
1 3 5
2 4 6
3 5 7
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: