Poj2274[The Race]题解--逆序对&二叉堆
来源:互联网 发布:阿里云测试招聘 编辑:程序博客网 时间:2024/06/05 10:48
【题目大意】
本题的大意就是有n个飞船,给出飞船的位置和速度,求飞船之间超越的总次数(结果要mod 1000000)和两个互相超越的飞船的编号(按时间大小排序,如果超越的总次数大于10000则输出前10000个)
【解题报告】
求飞船之间超越的总次数逆序对即可。
两个互相超越的飞船的编号:
用小根堆来做,按照飞船x超越飞船y的时间的大小建堆。
每次从堆顶取出一组超越的编号,则先验证编号是否成立,成立便将这两艘飞船的实时位置交换,并判断交换后这两艘飞船是否可以超越相邻的飞船或被相邻的飞船超越,如果验证成功则将这组超越的编号放进堆中。
注:
1.实时位置为目前飞船所在的位置(即经过?次超越或被超越后,飞船所在的位置)
2.输出两个互相超越的飞船的编号中注意当超越的时间相同时,按照超越的飞船的实时位置从小到大排序,而不是初始位置。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=250005,maxm=10005,maxv=105,tt=1000000;int n,num,len,ans,max_v,c[maxv],where[maxn];struct wjd{ int x,y,id;}a[maxn];struct ha{ double x; int s,t;}hep[maxn+maxm];inline int read_(){ int sum=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') sum=sum*10+ch-48,ch=getchar(); return sum;}void put_(double x,int s,int t){ hep[++len].x=x; hep[len].s=s; hep[len].t=t; int son=len; while (son!=1&&(hep[son].x<hep[son>>1].x||(hep[son].x==hep[son>>1].x&&where[hep[son].s]<where[hep[son>>1].s]))) swap(hep[son],hep[son>>1]),son>>=1; //按照超越时间为第一关键字,实时距离为第二关键字建小根堆}ha get_(){ ha sum=hep[1]; hep[1]=hep[len--]; int fa=1,son; while (fa*2<=len) { if (fa*2+1>len||(hep[fa*2].x<hep[fa*2+1].x||(hep[fa*2].x==hep[fa*2+1].x&&where[hep[fa*2].s]<where[hep[fa*2+1].s]))) son=fa*2; else son=fa*2+1; if (hep[son].x<hep[fa].x||(hep[son].x==hep[fa].x&&where[hep[son].s]<where[hep[fa].s])) { swap(hep[son],hep[fa]); fa=son; } else break; } return sum;}int lowbit_(int x){ return x&(-x);}int get_(int x)//树状数组{ int sum=0; while (x<=max_v) { sum+=c[x]; x+=lowbit_(x); } return sum;}void add_(int x,int da)//树状数组{ while (x>0) { c[x]+=da; x-=lowbit_(x); }}int main(){ freopen("2274.in","r",stdin); freopen("2274.out","w",stdout); n=read_(); len=ans=num=max_v=0; for (int i=1; i<=n; i++) a[i].x=read_(),a[i].y=read_(),a[i].id=i,where[i]=i,max_v=max(max_v,a[i].y); memset(c,0,sizeof(c)); for (int i=1; i<=n; i++) ans=(ans+get_(a[i].y))%tt,add_(a[i].y-1,1);//树状数组求逆序对 printf("%d\n",ans); for (int i=1; i<n; i++) { if (a[i].y<=a[i+1].y) continue; put_((double)(a[i+1].x-a[i].x)/(a[i].y-a[i+1].y),i,i+1); } num=0; while (num<10000&&len!=0) { ha x=get_(); if ((where[x.s]+1!=where[x.t])) continue;//判断已经不存在的情况 printf("%d %d\n",x.s,x.t); int s=where[x.s],t=where[x.t]; where[x.s]=t; where[x.t]=s;//记录实时位置 swap(a[s],a[t]);//将超越的两辆飞船交换位置 if (s>1&&(a[s-1].y>a[s].y)) if (where[a[s-1].id]+1==where[a[s].id]) put_((double)(a[s].x-a[s-1].x)/(a[s-1].y-a[s].y),a[s-1].id,a[s].id); if (t<n&&(a[t].y>a[t+1].y)) if (where[a[t].id]+1==where[a[t+1].id]) put_((double)(a[t+1].x-a[t].x)/(a[t].y-a[t+1].y),a[t].id,a[t+1].id);//判断超越后是否与新的相邻的飞船产生超越情况 ++num; } return 0;}
1 0
- Poj2274[The Race]题解--逆序对&二叉堆
- POJ2274[The Race]题解
- POJ2274【CEOI2003】The Race
- POJ2274——The Race
- [poj 2274] The Race 堆
- POJ 2274 [The Race]【堆+链表】
- poj 2274 The Race(逆序数+线段树)
- 【日常学习】【归并逆序对】codevs1688 求逆序对题解
- 【BZOJ】【P2789】【Poi2012】【Letters】【题解】【逆序对】
- 剑指offer题解 数组中的逆序对
- 平均数 题解【二分+求逆序对】
- [机房练习赛] 题解 求逆序对
- bzoj3295: [Cqoi2011]动态逆序对(题解2)
- [题解]bzoj3295 CQOI2011动态逆序对
- 【逆序对】In the Army Now
- 【POJ】【P2299】【Ultra-QuickSort】【题解】【求逆序对】
- 【BZOJ】【P3295】【CQOI2011】【动态逆序对】【题解】【树套树】
- 主席树初探 & bzoj 3295: [Cqoi2011] 动态逆序对 题解
- java中判断对象中属性值是否为空
- Linux Find 命令精通指南
- 静态代码块,非静态代码块,构造函数
- li下方存在间距空隙解决方案
- Java Thread Dump 日志分析
- Poj2274[The Race]题解--逆序对&二叉堆
- 面试前TCP/IP的总结与实践(三)
- 一步一步制作yaffs/yaffs2根文件系统(七)---真挚地道歉以及纠正前边出现的错误!
- google源码cartographer分析一
- POJ2389 Bull Math【大数】
- ajax提交form序列化
- 一些oracle-ora等错误记录
- UVa 514 Rails(经典栈)
- 互联网公司为啥不使用mysql分区表?