标签: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