zoukankan      html  css  js  c++  java
  • 【noip2012】开车旅行

    题意:

    给n个点的海拔h[i](不同点海拔不同) 两点的距离为abs(h[i]-h[j]) 有a、b两人轮流开车(只能往下标大的地方开) a每次会开到里当前点第二近的点 b每次会开到离当前点最近的点(距离相同h小的近) 给定x 如果a或b继续开距离和会大于x就不继续开。

    求两个问题

    1、给定x=x0求从哪点开始开能使a开的距离:b开的距离最小 不值相同取海拔高的

    2、给出m个询问 每个询问给定x1、y1 求从x1开始走且x=y1 a能走的距离和b能走的距离

    题解:

    不难发现(其实我一开始没发现 看了题解才知道TAT)从固定某点i走到的后若干个点和x没关系

    我们可以预处理出从i点走j个点 a、b走的距离 由于数据略大 可以用倍增做 move[i][j] 表示i开始走2^j步 a、b走的距离

    由于n比较大 不能n^2直接算离某点最近和第二进的点是谁

    可以先把所有的h[i]拿来排序 建立双向链表 显然i点的最近点一定是双向链表中i的前驱或后继 而次近点则还可能是前驱的前驱或后继的后继 每次求完将该点从双向链表中删除 这样就能o(n) 求出最近和次近点了

    然后我们就可以倍增轻松求出i开始走 且a、b走的距离<=x a、b分别走了多远了(第二个问题解决)

    对于第一个问题 也很简单 直接枚从哪个点开始走算ans就完了

    代码:

      1 #include <cstdio>
      2 #include <algorithm>
      3 typedef long long ll;
      4 using std::sort;
      5 const ll N=100001;
      6 struct info{
      7     ll t,ma,mb,bo;
      8     info(const ll a=0,const ll b=0,const ll c=0,const ll d=0):
      9         t(a),ma(b),mb(c),bo(d){}
     10 }move[N][20][2],save;
     11 struct inli{
     12     ll t,pr,ne;
     13     inli(const ll a=0,const ll b=0,const ll c=0):
     14         t(a),pr(b),ne(c){}
     15 }line[N];
     16 struct inim{
     17     ll t,s;
     18     inim(const ll a=0,const ll b=0):
     19         t(a),s(b){}
     20 }im[N];
     21 inline bool cmp(inim x,inim y){ return x.t<y.t; }
     22 ll h[N],sp[N],n,m,x0,ans;
     23 void makeline(){
     24     for (ll i=1;i<=n;i++){
     25         line[i].t=im[i].s;
     26         if (i>1) line[i].pr=i-1;
     27         if (i<n) line[i].ne=i+1;
     28     }
     29 }
     30 void makeres(ll &res1,ll &res2,ll t,ll a1){
     31     if (!a1) return;
     32     if (res1==0 || abs(h[t]-h[a1])<abs(h[t]-h[res1]) || 
     33     (abs(h[t]-h[a1])==abs(h[t]-h[res1]) && h[a1]<h[res1])) res2=res1,res1=a1;
     34     else if (res2==0 || abs(h[t]-h[a1])<abs(h[t]-h[res2]) || 
     35     (abs(h[t]-h[a1])==abs(h[t]-h[res2]) && h[a1]<h[res2])) res2=a1;
     36 }
     37 inim getmove(ll t,ll a1,ll a2,ll a3,ll a4){
     38     ll res1=0,res2=0;
     39     if (t==99)
     40     t=99;
     41     makeres(res1,res2,t,line[a1].t);
     42     makeres(res1,res2,t,line[a2].t);
     43     makeres(res1,res2,t,line[a3].t);
     44     makeres(res1,res2,t,line[a4].t);
     45     if (!res1) return inim(res2,res1);
     46     return inim(res1,res2);
     47 }
     48 void makemove0(){
     49     for (ll i=1;i<n;i++){
     50         if (i==2)
     51         i=2;
     52         inim x=getmove(i,line[sp[i]].pr,line[sp[i]].pr ? line[line[sp[i]].pr].pr : 0,
     53         line[sp[i]].ne,line[sp[i]].ne ? line[line[sp[i]].ne].ne : 0);
     54         move[i][0][0].t=x.t;
     55         move[i][0][0].ma=abs(h[i]-h[x.t]);
     56         move[i][0][0].bo=1;
     57         if (x.s){
     58             move[i][0][1].t=x.s;
     59             move[i][0][1].mb=abs(h[i]-h[x.s]);
     60             move[i][0][1].bo=0;
     61         }
     62         line[line[sp[i]].pr].ne=line[sp[i]].ne;
     63         line[line[sp[i]].ne].pr=line[sp[i]].pr;
     64     }
     65 }
     66 void makemove(){
     67     makemove0();
     68     for (ll i=n;i;i--)
     69     for (ll k=0;k<=1;k++){
     70         if (i==1)
     71         i=1;
     72     for (ll j=1;move[move[i][j-1][k].t][j-1][move[i][j-1][k].bo].t;j++){
     73         info x=move[move[i][j-1][k].t][j-1][move[i][j-1][k].bo];
     74         move[i][j][k].t=x.t;
     75         move[i][j][k].bo=x.bo;
     76         move[i][j][k].ma=move[i][j-1][k].ma+x.ma;
     77         move[i][j][k].mb=move[i][j-1][k].mb+x.mb;
     78     }
     79     }
     80 }
     81 info getans(ll x,ll y){
     82     info res=info(x,0,0,1);
     83     for (;y>=move[res.t][0][res.bo].ma+move[res.t][0][res.bo].mb && move[res.t][0][res.bo].t;){
     84         ll i=0,st=res.t,sb=res.bo;
     85         while (y>=move[st][i][sb].ma+move[st][i][sb].mb && move[st][i][sb].t) ++i;
     86         --i;
     87         y-=move[st][i][sb].ma+move[st][i][sb].mb;
     88         res.t=move[st][i][sb].t;
     89         res.bo=move[st][i][sb].bo;
     90         res.ma+=move[st][i][sb].ma;
     91         res.mb+=move[st][i][sb].mb;
     92     }
     93     return res;
     94 }
     95 bool check(info x,ll y){
     96     if (!ans) return 1;
     97     if (!x.ma){
     98         if (save.ma) return 0;
     99         else return (h[y]>h[ans]);
    100     }
    101     if (!save.mb) return 1;
    102     if (save.ma*x.mb<save.mb*x.ma || (save.ma*x.mb==save.mb*x.ma && h[y]>h[ans])) return 1;
    103     else return 0;
    104 }
    105 int main(){
    106     freopen("drive.in","r",stdin);
    107     freopen("drive.out","w",stdout);
    108     scanf("%I64d",&n);
    109     for (ll i=1;i<=n;i++){
    110         scanf("%I64d",&h[i]);
    111         im[i]=inim(h[i],i);
    112     }
    113     sort(im+1,im+n+1,cmp);
    114     for (ll i=1;i<=n;i++) sp[im[i].s]=i;
    115     makeline();
    116     makemove();
    117     scanf("%I64d",&x0);
    118     for (ll i=1;i<=n;i++){
    119         info x=getans(i,x0);
    120         if (check(x,i)) save=x,ans=i;
    121     }
    122     printf("%I64d
    ",ans);
    123     scanf("%I64d",&m);
    124     ll x,y;
    125     for (ll i=1;i<=m;i++){
    126         if (i==54)
    127         i=54;
    128         scanf("%I64d%I64d",&x,&y);
    129         info xx=getans(x,y);
    130         printf("%I64d %I64d
    ",xx.mb,xx.ma);
    131     }
    132     fclose(stdin);
    133     fclose(stdout);
    134 }
    View Code
  • 相关阅读:
    C# 5.0 in a Nutshell 读书笔记(一) 野峰
    CLR via C# 4th Edition 野峰
    杰佛里给 Windows Server 2019 Automation with PowerShell 一书所写序言 野峰
    .NET的跨平台调用一例(PreserveSig) 野峰
    Http请求响应
    为什么不要追随新的linux发行版
    make: *** [out/host/linuxx86/obj/STATIC_LIBRARIES/libgtest_host_intermediates/gtestall.o] Error change
    linux 下at&t语法的汇编之hello world!!
    android 编译错误001_cm9 for onda elite vi10
    把vim当作16进制编辑器使用、、
  • 原文地址:https://www.cnblogs.com/g-word/p/3369447.html
Copyright © 2011-2022 走看看