zoukankan      html  css  js  c++  java
  • NOIP2012提高组D1T3 开车旅行

    n<=100000个山,每个山有高度,从一个山到另一个山代价为高度差,有A和B两人一起开车,A每次选前进方向的次近山,B选最近,保证山高度不同且如果代价相同的山低的代价算小,每次旅行先A走,然后B,然后AB轮流开车,旅行如果下一次找不到目的地或者下一次到目的地时总代价超过了指定的X,他们就会停下。现完成两个任务:一,告诉X0,问从哪个点开始完成一次预算代价为X0的旅行会使A的路程比B的路程最小;二,m个询问,每次问从Si做预算Xi的旅行,A和B的行驶路程。

    首先需要知道每个人后面的最近和次近山,双向链表、set、乱七八糟,随便搞。这里选双向链表,前面需要一个离散化:把每个数的排名连接起来,从1到n扫一次,每次用一个数的前驱、前驱的前驱、后继、后继的后继来比较出最近和次近,然后在双向链表中删除之。

    由于A和B走一步的方式不一样,这样“跳”会比较复杂,不如把“跳”一步定义成A和B都走一次,这样可以处理一个ST表,表示从点i跳2^j步跳到哪里,以及期间A和B的行驶路程。用这个可以轻松算出所有的询问。

    询问一:枚举从每个点开始跳,看最远能跳到哪,然后最后一步看A能不能再开一次。

    询问二:同理。

    倍增写挂了,开了个临时变量now来跳结果用i来跳。。。浪费了一晚上

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<math.h>
      4 #include<stdlib.h>
      5 #include<assert.h>
      6 #include<algorithm>
      7 //#include<queue>
      8 //#include<iostream>
      9 using namespace std;
     10 
     11 bool isdigit(char c) {return c>='0' && c<='9';}
     12 int qread()
     13 {
     14     char c;int s=0,t=1;while (!isdigit(c=getchar())) (c=='-' && (t=-1));
     15     do s=s*10+c-'0'; while (isdigit(c=getchar()));return s*t;
     16 }
     17 
     18 int n;
     19 #define maxn 100011
     20 int pre[maxn],suc[maxn],zui[maxn],zuilu[maxn],ci[maxn],cilu[maxn],Rank[maxn],lisan[maxn],id[maxn];
     21 #define LL long long
     22 LL hei[maxn],f[maxn][22],fa[maxn][22],fb[maxn][22];
     23 void prepare()
     24 {
     25     for (int i=1;i<=n+1;i++) pre[i]=i-1;
     26     for (int i=0;i<=n;i++) suc[i]=i+1;
     27     for (int i=1;i<=n;i++) lisan[i]=hei[i];
     28     sort(lisan+1,lisan+1+n);
     29     for (int i=1;i<=n;i++) Rank[i]=lower_bound(lisan+1,lisan+1+n,hei[i])-lisan,id[Rank[i]]=i;
     30     for (int i=2;i<=n;i++) assert(lisan[i]!=lisan[i-1]);
     31 //    for (int i=1;i<=n;i++) cout<<Rank[i]<<' ';cout<<endl;
     32     hei[0]=-1e15;id[0]=id[n+1]=0;
     33     for (int i=1;i<=n;i++)
     34     {
     35         LL x,y;
     36         if (fabs((x=hei[id[suc[Rank[i]]]])-hei[i])<fabs((y=hei[id[pre[Rank[i]]]])-hei[i]))
     37         {
     38             zui[i]=id[suc[Rank[i]]];
     39             zuilu[i]=fabs(x-hei[i]);
     40             if (fabs((x=hei[id[suc[suc[Rank[i]]]]])-hei[i])<fabs(y-hei[i]))
     41             {
     42                 ci[i]=id[suc[suc[Rank[i]]]];
     43                 cilu[i]=fabs(x-hei[i]);
     44             }
     45             else
     46             {
     47                 ci[i]=id[pre[Rank[i]]];
     48                 cilu[i]=fabs(y-hei[i]);
     49             }
     50         }
     51         else
     52         {
     53             zui[i]=id[pre[Rank[i]]];
     54             zuilu[i]=fabs(y-hei[i]);
     55             if (fabs(x-hei[i])<fabs((y=hei[id[pre[pre[Rank[i]]]]])-hei[i]))
     56             {
     57                 ci[i]=id[suc[Rank[i]]];
     58                 cilu[i]=fabs(x-hei[i]);
     59             }
     60             else
     61             {
     62                 ci[i]=id[pre[pre[Rank[i]]]];
     63                 cilu[i]=fabs(y-hei[i]);
     64             }
     65         }
     66         pre[suc[Rank[i]]]=pre[Rank[i]];
     67         suc[pre[Rank[i]]]=suc[Rank[i]];
     68     }
     69     for (int i=1;i<=n;i++) f[i][0]=zui[ci[i]],fa[i][0]=cilu[i],fb[i][0]=zuilu[ci[i]];
     70     for (int j=1;j<=20;j++)
     71         for (int i=1,to=(n-(1<<j)+1);i<=to;i++)
     72         {
     73             f[i][j]=f[f[i][j-1]][j-1];
     74             fa[i][j]=fa[i][j-1]+fa[f[i][j-1]][j-1];
     75             fb[i][j]=fb[i][j-1]+fb[f[i][j-1]][j-1];
     76 //            cout<<i<<' '<<j-1<<' '<<f[i][j-1]<<' '<<fa[i][j-1]<<' '<<fb[i][j-1]<<endl;
     77         }
     78 //    for(int i=1;i<=n;i++,puts("")) for(int j=0;j<=1;j++) printf("[%lld %lld %lld] ",f[i][j],fa[i][j],fb[i][j]);
     79 }
     80 
     81 void work1()
     82 {
     83     int x0=qread();
     84     bool flag=0;
     85     LL ansa=0,ansb=0;int ans=0;
     86     for (int i=1;i<=n;i++)
     87     {
     88         LL tota=0,totb=0;int now=i;
     89         for (int j=20;j>=0;j--) if (f[now][j])
     90             if (fa[now][j]+fb[now][j]+tota+totb<=x0)
     91             {
     92                 tota+=fa[now][j];
     93                 totb+=fb[now][j];
     94                 now=f[now][j];
     95 //        if (i==2) cout<<tota<<' '<<totb<<' '<<now<<endl;
     96             }
     97         if (ci[now] && cilu[now]+tota+totb<=x0) tota+=cilu[now],now=ci[now];
     98         if (!flag) ansa=tota,ansb=totb,flag=1,ans=i;
     99         else if (totb)
    100         {
    101             if (!ansb) ansa=tota,ansb=totb,ans=i;
    102             else if (1.0*ansa/ansb>1.0*tota/totb) ansa=tota,ansb=totb,ans=i;
    103             else if (fabs(1.0*ansa/ansb-1.0*tota/totb)<1e-9 && hei[i]>hei[ans]) ans=i;
    104         }
    105         else if (!ansb && hei[i]>hei[ans]) ans=i;
    106 //        cout<<"now"<<now<<endl;
    107 //        cout<<tota<<' '<<totb<<endl;
    108     }
    109     printf("%d
    ",ans);
    110 }
    111 
    112 void work2()
    113 {
    114     int m=qread();int x,y;
    115     while (m--)
    116     {
    117         x=qread(),y=qread();
    118         LL tota=0,totb=0;
    119         for (int j=20;j>=0;j--) if (f[x][j])
    120             if (tota+fa[x][j]+totb+fb[x][j]<=y)
    121             {
    122                 tota+=fa[x][j];
    123                 totb+=fb[x][j];
    124                 x=f[x][j];
    125             }
    126         if (ci[x] && cilu[x]+tota+totb<=y) tota+=cilu[x];
    127         printf("%lld %lld
    ",tota,totb);
    128     }
    129 }
    130 
    131 int main()
    132 {
    133     n=qread();
    134     for (int i=1;i<=n;i++) hei[i]=qread();
    135     prepare();
    136     work1();
    137     work2();
    138 //    for (int i=1;i<=n;i++) cout<<zui[i]<<' '<<zuilu[i]<<' '<<ci[i]<<' '<<cilu[i]<<endl;
    139     return 0;
    140 }
    View Code
  • 相关阅读:
    [转]HDR渲染器的实现(基于OpenGL)
    32位微机的内存管理模式
    王爽汇编检测点1.1
    标志位的说明
    通用寄存器的作用
    Debug初次使用
    昨天纠结了一天要始学习dos汇编还是win32汇编,终于想通了
    CPU对存储器的读写(二、数据总线、控制总线)
    CPU对存储器的读写(一、地址总线)
    段寄存器的引用
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7774858.html
Copyright © 2011-2022 走看看