Noip2012 开车旅行

Posted 这里有十二吨芒果

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Noip2012 开车旅行相关的知识,希望对你有一定的参考价值。

(题目太长了复制没意义QAQ)

芒果君:看着别人的题解还是写了2h+啊,真是道神题……

第一个障碍:每个城市高度都不一样,先存坐标和ID再排序,然后搞个双向链表(l,r),然后只要有任何一个地方把这4个参数搞错就会WA成狗>_<;

第二个:预处理一大堆,你需要3个倍增的数组,A、B、还有他们两个一起跳,因为要统计他们各自的路程还要保证效率;

第三个:如果你预处理都对了,然后一起跳但是忘了特判A还能不能再走,Waaaaaaaaa…………

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cstdlib>
  7 #include<vector>
  8 #include<queue>
  9 #include<stack>
 10 #define inf 1<<29
 11 #define maxn 100010
 12 #define ll long long
 13 using namespace std;
 14 struct Node{
 15     int i,v,l,r;//编号、海拔、(链表)前驱、后继 
 16     bool operator<(const Node &x)const{return v<x.v;}
 17 }d[maxn];
 18 int L,R,n,m,disa,disb,pos=n,na[maxn],nb[maxn],p[maxn],f[maxn][20],sta[maxn][20],stb[maxn][20];
 19 ll x;
 20 double nowmin=1ll<<62;
 21 ll read()
 22 {
 23     ll ret(0),f=1;
 24     char ch=getchar();
 25     while(ch<0||ch>9){
 26         if(ch==-) f=-1;
 27         ch=getchar();
 28     }
 29     while(ch>=0&&ch<=9){
 30         ret=ret*10+ch-0;
 31         ch=getchar();
 32     }
 33     return ret*f;
 34 }
 35 bool left(int now)
 36 {
 37     if(!L) return false;
 38     if(!R) return true;
 39     return d[now].v-d[L].v<=d[R].v-d[now].v;
 40 }
 41 int pd(int X,int Y,int now)
 42 {
 43     if(!X) return d[Y].i;
 44     if(!Y) return d[X].i;
 45     return d[now].v-d[X].v<=d[Y].v-d[now].v?d[X].i:d[Y].i;
 46 }
 47 void init()
 48 {
 49     for(int j=1;j<=19;++j)
 50         for(int i=1;i<=n;++i){
 51             f[i][j]=f[f[i][j-1]][j-1];
 52             sta[i][j]=sta[i][j-1]+sta[f[i][j-1]][j-1];
 53             stb[i][j]=stb[i][j-1]+stb[f[i][j-1]][j-1];
 54         }
 55 }
 56 void solve(ll x,int now)
 57 {
 58     disa=disb=0;
 59     for(int i=19;i>=0;--i){
 60         if(f[now][i]&&(1ll*disa+disb+sta[now][i]+stb[now][i])<=x){
 61             disa+=sta[now][i];
 62             disb+=stb[now][i];
 63             now=f[now][i];
 64         }
 65     }
 66     if(na[now]&&disa+disb+sta[now][0]<=x) disa+=sta[now][0];
 67 }
 68 int main()
 69 {
 70     n=read();
 71     for(int i=1;i<=n;++i) d[i].v=read();
 72     for(int i=1;i<=n;++i) d[i].i=i;
 73     sort(d+1,d+n+1);
 74     for(int i=1;i<=n;++i) p[d[i].i]=i;
 75     for(int i=1;i<=n;++i) d[i].l=i-1,d[i].r=i+1;
 76     d[1].l=d[n].r=0;
 77     for(int i=1;i<=n;++i){
 78         int now=p[i];
 79         L=d[now].l,R=d[now].r;
 80         if(left(now)) nb[i]=d[L].i,na[i]=pd(d[L].l,R,now);//找最近和第二近的 
 81         else nb[i]=d[R].i,na[i]=pd(L,d[R].r,now);
 82         if(L) d[L].r=R;
 83         if(R) d[R].l=L;
 84     }
 85     for(int i=1;i<=n;++i){
 86         f[i][0]=nb[na[i]];//a跳完b跳==a、b一起跳 
 87         sta[i][0]=abs(d[p[i]].v-d[p[na[i]]].v);
 88         stb[i][0]=abs(d[p[f[i][0]]].v-d[p[na[i]]].v);
 89     }
 90     init();
 91     x=read(),m=read();
 92     for(int i=1;i<=n;++i){
 93         solve(x,i);
 94         if(disb&&(nowmin>1.0*disa/disb)){
 95             nowmin=1.0*disa/disb;
 96             pos=i;
 97         }
 98     }
 99     printf("%d\n",pos);
100     for(int i=1;i<=m;++i){
101         pos=read(),x=read();
102         solve(x,pos);
103         printf("%d %d\n",disa,disb);
104     }
105     return 0;
106 }

 

以上是关于Noip2012 开车旅行的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2012开车旅行

NOIP2012-开车旅行

Cogs1264. [NOIP2012] 开车旅行(70分 暴力)

Noip2012 开车旅行

NOIP2012开车旅行 倍增

noip2012开车旅行 [倍增]