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 }