标签:des style http os io for 数据 ar art

5 1 1 5 1 7 1 3 3 5 5
1 2 1 1 0
题目意思: 给你n个坐标,然后其中任意一个点,假如有s个点的横坐标和纵坐标都不大于这个点,那么这个点的价值为s,
最后让你输出 价值从1~n-1,的点的个数
比赛的时候有一个队做过这个题,很快做出来了,我纠结好久(太菜了%>_<%),一直想着给x排序,然后再给y排序,
希望得出什么规律,最后想到了给x排序后,判断这个点的价值,需要快速查询前面点(按x以排序)不比他大的的点的个数(数据很大,易超时),终于想到线段树(⊙o⊙)…,用线段树保存le~ri已经存在的个数
具体的思路说完了,上代码了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)
using namespace std;
#define N 32005
struct stud1{
int le,ri;
int va;
}f[N*4]; //刚开始没有乘4,搞得答案一直对不上
struct stud{
int x,y;
}s[N];
int ans[N];
int cmp(stud a,stud b)
{
if(a.x==b.x)
return a.y<b.y; //记得x相同时排y
return a.x<b.x;
}
void build(int pos,int le,int ri)
{
f[pos].le=le;
f[pos].ri=ri;
f[pos].va=0;
if(le==ri) return ;
int mid=MID(le,ri);
build(L(pos),le,mid);
build(R(pos),mid+1,ri);
}
void update(int pos,int le)
{
f[pos].va++;
if(f[pos].le==le&&le==f[pos].ri)
return ;
int mid=MID(f[pos].le,f[pos].ri);
if(mid>=le)
update(L(pos),le);
else
update(R(pos),le);
}
int query(int pos,int le,int ri)
{
if(f[pos].le==le&&f[pos].ri==ri)
return f[pos].va;
int mid=MID(f[pos].le,f[pos].ri);
if(mid>=ri)
return query(L(pos),le,ri);
else
if(mid<le)
return query(R(pos),le,ri);
return query(L(pos),le,mid)+query(R(pos),mid+1,ri);
}
int main()
{
int i,n;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++)
scanf("%d%d",&s[i].x,&s[i].y);
memset(ans,0,sizeof(ans));
sort(s,s+n,cmp);
build(1,0,N-1);
for(i=0;i<n;i++)
{
int x=query(1,0,s[i].y);
ans[x]++;
update(1,s[i].y);
}
for(i=0;i<n;i++)
printf("%d\n",ans[i]);
}
return 0;
}
标签:des style http os io for 数据 ar art
原文地址:http://blog.csdn.net/u014737310/article/details/38779003