【NOIP2012提高组】开车旅行
2016-03-18 18:58
525 查看
Description
现在有n个城市,每个城市有它的高度Hi,保证每个Hi互不相同。我们定义两个城市之间的距离dis(i,j)=|Hi−Hj|dis(i,j)=|Hi−Hj|,并且只能从编号小的城市去到编号大的城市。现在有两个人,小A和小B要开车(雾)去旅行。小A先开一天,小B再开一天。每一天都可以从一个开到另一个城市。小A会选择去离当前城市第二近的城市,小B会选择去离当前城市最近的那个城市。如果他们行驶的总路程将会超过给定的X就会不继续开车(∩_∩),结束旅行。求:1:给定一个X,求从哪一个城市出发,小A行驶的路程/小B行驶的路程最小。(认为一个数/0=∞)。若有多个城市相等,选择高度最高的那个。
2:给出m个询问,每次询问从S出发,限制为X,小A走的路程和小B走的路程
Solution
注意小A和小B开同一辆车,感觉超级坑,TAT用什么
题目很显然,就是用一个数据结构维护最小值和次小值,可以维护的数据结构有很多啦,这么经典的要求。可以用什么双向链表啊,权值线段树啊(因为下标线段树不容易转移值域,而权值线段树很容易),平衡树啊等等。怎么做
打个权值线段树练练手,维护这段值域区间的坐标最大值和最小值(权值线段树的经典维护方法)。为什么两个都要维护呢?
因为,我要在左边找相近的,可能比a[i]小,可能比a[i]大,所以要找a[i]+1到max的坐标小的,和1到a[i]-1找一个大的。一共有四个值,所以排一个序之后,在取前两个,打c++就是好。
然后,因为走得路程在给出的范围下是固定的,所以,可以打经典的倍增算法,像个lca一样。
离散化!
不离散化,要爆啊!!!开long long啊!
这个吃分啊,吃了70多分。Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define fo(i,a,b) for(i=a;i<=b;i++) #define fod(i,a,b) for(i=a;i>=b;i--) #define ll long long using namespace std; const int maxn=100007; ll i,j,k,l,n,m,x0; double ans,ans1; ll a[maxn]; struct node{ int l,r; }t[maxn*10]; struct noo{ int o,p,q; }op[maxn*10]; struct nod{ ll a,b; }pai[maxn*10]; int f[maxn][18]; ll g[maxn][18][2],ans2,xx0,ber,ber1; ll b[maxn],c[maxn],d[maxn],e[maxn]; void insert(int x,int l,int r,int y){ if(l==r){ t[x].l=t[x].r=l; } else{ int mid=(l+r)/2; if(y<=mid)insert(x*2,l,mid,y); else insert(x*2+1,mid+1,r,y); t[x].l=min(t[x*2].l,t[x*2+1].l); t[x].r=max(t[x*2].r,t[x*2+1].r); } } int dexiao(int x,int l,int r,int y,int z){ if(y>z)return n+1; if(l==y&&r==z){ return t[x].l; } else{ int mid=(l+r)/2; if(z<=mid)return dexiao(x*2,l,mid,y,z); else if(y>mid)return dexiao(x*2+1,mid+1,r,y,z); else{ return min(dexiao(x*2,l,mid,y,mid),dexiao(x*2+1,mid+1,r,mid+1,z)); } } } int deda(int x,int l,int r,int y,int z){ if(y>z)return 0; if(l==y&&r==z){ return t[x].r; } else{ int mid=(l+r)/2; if(z<=mid)return deda(x*2,l,mid,y,z); else if(y>mid)return deda(x*2+1,mid+1,r,y,z); else{ return max(deda(x*2,l,mid,y,mid),deda(x*2+1,mid+1,r,mid+1,z)); } } } void doing(int x,int y){ int i; ber1=ber=0; fod(i,17,0){ if(g[x][i][0]+g[x][i][1]<=y){ y-=(g[x][i][0]+g[x][i][1]); ber=ber+g[x][i][0];ber1=ber1+g[x][i][1]; x=f[x][i]; } } if(g[x][0][0]<=y)ber+=g[x][0][0]; } bool cmp(nod x,nod y){return x.b<y.b||x.b==y.b&&x.a<y.a;} bool cmp1(noo x,noo y){return x.o<y.o;} int main(){ scanf("%d",&n); a[0]=0x7fffffff; fo(i,1,n){ scanf("%lld",&a[i]); op[i].o=a[i];op[i].p=i; } sort(op+1,op+n+1,cmp1); fo(i,1,n)d[op[i].p]=i,e[i]=op[i].p; fo(i,1,n*10)t[i].l=n+1,t[i].r=0; fod(i,n,1){ pai[1].a=dexiao(1,1,n,d[i]+1,n); pai[2].a=deda(1,1,n,1,d[i]-1); pai[3].a=dexiao(1,1,n,pai[1].a+1,n); pai[4].a=deda(1,1,n,1,pai[2].a-1); fo(j,1,4)pai[j].b=abs(a[i]-a[e[pai[j].a]]); sort(pai+1,pai+5,cmp); if(pai[2].a!=0&&pai[2].a!=1+n)b[i]=e[pai[2].a]; if(pai[1].a!=0&&pai[1].a!=1+n)c[i]=e[pai[1].a]; insert(1,1,n,d[i]); } fo(i,1,n){ f[i][0]=c[b[i]]; g[i][0][0]=abs(a[i]-a[b[i]]); g[i][0][1]=abs(a[b[i]]-a[c[b[i]]]); } fo(i,1,17){ fo(j,1,n){ f[j][i]=f[f[j][i-1]][i-1]; g[j][i][0]=g[f[j][i-1]][i-1][0]+g[j][i-1][0]; g[j][i][1]=g[f[j][i-1]][i-1][1]+g[j][i-1][1]; } } ans=0x7fffffff; scanf("%d",&xx0); fo(i,1,n){ doing(i,xx0); if(ber1!=0)ans1=ber*1.0/ber1;else ans1=0x7fffffff; if(ans1<ans||ans1==ans&&a[ans2]<a[i]) ans=ans1,ans2=i; } printf("%d\n",ans2); scanf("%d",&m); fo(i,1,m){ scanf("%d%d",&k,&l); ber=ber1=0; doing(k,l); printf("%lld %lld\n",ber,ber1); } }
相关文章推荐
- android日志打印代码 logcat
- 什么是面向连接服务?什么是无连接服务?
- HDOJ 1089 A+B for Input-Output Practice (I)
- 程序员之路漫漫兮,吾将上下而求索2008-8-25 12:50阅读(1)
- 数学计算
- CSS框模型:一切皆为框 — 从行框说起
- Eclipse中使用tomcat 8服务器初级教程
- 【并查集】HAOI破译密文
- 面试题目记录
- Jenkins部署Windows UI自动化的调度权限问题
- LightOJ 1140 How Many Zeroes?
- 搭建高质量的Android项目框架系列一
- Godaddy新手教程
- 初探React与D3的结合-或许是visualization的新突破?
- HDU5643-King's Game
- MySQL行锁深入研究
- HDU 2866 Special Prime 找规律
- 使用TransactionProxyFactoryBean代理事务
- iOS 开发 发布 证书 详细说明
- 常用的云服务器,云数据库,高速缓存服务器