poj 2481 Cows 树状数组or线段树
2016-04-16 10:35
309 查看
题意:
给n个区间,问第i个区间是多少个区间的子区间。
分析:
可以吧每一个线段看成是一个点,这样的话就等价于问一个点的左上方有多少个点?这样就和Stars那题一样了。
因为是求左上方有多少个点,那么把所有点按照y从大到小排列,这样就可以按照顺序求出0~x之间有多少个点,就是它左上方的点了。
需要重点的处理。
树状数组:
线段树:
用线段树也是先排序,然后再求区间【0,x】的和,再单点更新。
给n个区间,问第i个区间是多少个区间的子区间。
分析:
可以吧每一个线段看成是一个点,这样的话就等价于问一个点的左上方有多少个点?这样就和Stars那题一样了。
因为是求左上方有多少个点,那么把所有点按照y从大到小排列,这样就可以按照顺序求出0~x之间有多少个点,就是它左上方的点了。
需要重点的处理。
树状数组:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+5; struct point { int x,y,id; }p ; bool cmp(const point &a,const point &b) { if(a.y==b.y)return a.x<b.x; return a.y>b.y; } int c ,ans ; int lowbit(int x){return x&(-x);} int getsum(int x) { int sum =0; for(int i=x;i>0;i-=lowbit(i))sum+=c[i]; return sum; } void add(int x) { for(int i=x;i<N;i+=lowbit(i))c[i]++; } int main() { int n,x,y; while(~scanf("%d",&n)&&n){ memset(ans,0,sizeof(ans)); memset(c,0,sizeof(c)); for(int i=0;i<n;i++){ scanf("%d%d",&p[i].x,&p[i].y); ++p[i].x; p[i].id=i; } sort(p,p+n,cmp); for(int i=0;i<n;i++){ if(i&&p[i-1].x==p[i].x&&p[i-1].y==p[i].y)ans[p[i].id]=ans[p[i-1].id]; else{ ans[p[i].id]=getsum(p[i].x); } add(p[i].x); } for(int i=0;i<n-1;i++) printf("%d ",ans[i]); printf("%d\n",ans[n-1]); } return 0; }
线段树:
用线段树也是先排序,然后再求区间【0,x】的和,再单点更新。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int N=1e5+5; int sum[N<<2]; struct point { int x,y,num,ans; }p ; bool cmp(const point &a,const point &b) { if(a.y==b.y)return a.x<b.x; return a.y>b.y; } bool cmp2(const point &a,const point &b) { return a.num<b.num; } void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } int query(int a,int b,int l,int r,int rt) { if(a<=l&&r<=b)return sum[rt]; int m=(l+r)>>1; int ans=0; if(a<=m)ans=query(a,b,lson); if(b>m)ans+=query(a,b,rson); return ans; } void update(int x,int l,int r,int rt) { if(l==r){sum[rt]++;return;} int m=(l+r)>>1; if(x<=m)update(x,lson); else update(x,rson); pushup(rt); } int main() { int n,x,y; while(~scanf("%d",&n)&&n){ memset(sum,0,sizeof(sum)); for(int i=0;i<n;i++){ scanf("%d%d",&p[i].x,&p[i].y);p[i].num=i; } sort(p,p+n,cmp); for(int i=0;i<n;i++){ if(i&&p[i].x==p[i-1].x&&p[i].y==p[i-1].y)p[i].ans=p[i-1].ans; else p[i].ans=query(0,p[i].x,0,1e5,1); // printf("%d ",p[i].ans); update(p[i].x,0,1e5,1); } sort(p,p+n,cmp2); for(int i=0;i<n-1;i++){ printf("%d ",p[i].ans); } printf("%d\n",p[n-1].ans); } return 0; }
相关文章推荐
- Android Studio 项目中,哪些文件应该忽略而不提交到svn的服务器中?
- Eclipse_Android问题锦集
- 【学习OpenCV】—— 深入了解 cv::Mat
- TCP/IP卷一(第四章学习)
- 工厂方法模式的理解
- iOS开发中设置圆角的方法
- 指针与引用的区别
- 单例模式
- 《仙境之路》真是个不错的电影
- 好久没来博客园写日志了
- 51. (转) Android学习路线
- 物料BOM和生产订单BOM的区别
- 排序算法---1
- 栈
- Python简单实现TCP包发送十六进制数据的方法
- 让QT跑在ARM开发板上
- FZU 2140 Forever 0.5(找规律,几何)
- OpenstackCep分布式存储的功能实现和适用场景
- 0x0000006B蓝屏解决方法
- 集合的嵌套遍历