luogu1081 [NOIp2012]开车旅行 (STL::multiset+倍增)
先用不管什么方法求出来从每个点出发,A走到哪、B走到哪(我写了一个很沙雕的STL)
然后把每个点拆成两个点,分别表示A从这里出发和B从这里出发,然后连边是要A连到B、B连到A、边长就是这次走的路径长度
为了方便,把不能继续走的点连到一个假节点1上(不连应该也无所谓)
然后我们预处理倍增,但要把A走的距离和B走的距离分开来算
之后就每次往上跳找第一个不能走的地方,然后算一算答案就行了
(整数除整数别忘了先换成double或者乘个1.0.............)
1 #include<bits/stdc++.h> 2 #define pa pair<ll,int> 3 #define lowb(x) ((x)&(-(x))) 4 #define REP(i,n0,n) for(i=n0;i<=n;i++) 5 #define PER(i,n0,n) for(i=n;i>=n0;i--) 6 #define MAX(a,b) ((a>b)?a:b) 7 #define MIN(a,b) ((a<b)?a:b) 8 #define CLR(a,x) memset(a,x,sizeof(a)) 9 #define rei register int 10 using namespace std; 11 typedef long long ll; 12 const int maxn=1e5+10,logn=20; 13 const ll inf=1e16; 14 15 inline ll rd(){ 16 ll x=0;char c=getchar();int neg=1; 17 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 18 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 19 return x*neg; 20 } 21 22 int N,M,fa[maxn<<1][logn]; 23 ll h[maxn],dis1[maxn<<1][logn],dis2[maxn<<1][logn]; 24 multiset<pa > st; 25 bool flag[maxn<<1]; 26 27 void getfa(int x){ 28 flag[x]=1; 29 if(fa[x][0]&&!flag[fa[x][0]]) getfa(fa[x][0]); 30 for(int i=1;fa[x][i-1]&&fa[fa[x][i-1]][i-1];i++){ 31 fa[x][i]=fa[fa[x][i-1]][i-1]; 32 dis1[x][i]=dis1[x][i-1]+dis1[fa[x][i-1]][i-1]; 33 dis2[x][i]=dis2[x][i-1]+dis2[fa[x][i-1]][i-1]; 34 } 35 } 36 void getdis(ll &d1,ll &d2,int x,ll bnd){ 37 d1=d2=0; 38 for(int i=19;i>=0;i--){ 39 if(fa[x][i]&&dis1[x][i]+dis2[x][i]<=bnd){ 40 bnd-=dis1[x][i]+dis2[x][i]; 41 d1+=dis1[x][i],d2+=dis2[x][i]; 42 x=fa[x][i]; 43 } 44 } 45 } 46 47 int main(){ 48 // freopen("1081.in","r",stdin); 49 rei i,j,k; 50 N=rd(); 51 for(i=1;i<=N;i++) h[i]=rd(); 52 st.insert(make_pair(inf,1)); 53 for(i=N;i;i--){ 54 multiset<pa>::iterator it=st.lower_bound(make_pair(h[i],0)); 55 ll mi=inf;int ma=0; 56 if(it->first!=inf) 57 mi=it->first-h[i],ma=it->second; 58 if(it!=st.begin()){ 59 it--; 60 if(h[i]-it->first<=mi) mi=h[i]-it->first,ma=it->second; 61 } 62 fa[i<<1|1][0]=ma?(ma<<1):1; 63 dis2[i<<1|1][0]=mi; 64 65 ll mi2=inf;int ma2=0; 66 if(mi!=inf){ 67 it=st.lower_bound(make_pair(h[i]+mi,0)); 68 if(it->first!=inf&&it->first==h[i]+mi&&it->second!=ma){ 69 mi2=mi,ma2=it->second; 70 }else{ 71 if(it->first!=inf&&it->first-h[i]==mi) it++; 72 if(it->first!=inf&&it->first-h[i]>mi) 73 mi2=it->first-h[i],ma2=it->second; 74 it=st.lower_bound(make_pair(h[i]-mi,0)); 75 if(it!=st.begin()){ 76 it--; 77 if(h[i]-it->first>mi&&h[i]-it->first<=mi2) 78 mi2=h[i]-it->first,ma2=it->second; 79 } 80 } 81 } 82 83 fa[i<<1][0]=ma2?(ma2<<1|1):1; 84 dis1[i<<1][0]=mi2; 85 st.insert(make_pair(h[i],i)); 86 // printf("%d %d %lld %d %lld\n",i,fa[i<<1|1][0],mi,fa[i<<1][0],mi2); 87 } 88 // for(i=1;i<=(N<<1|1);i++) printf("%d %d\n",i,fa[i][0]); 89 for(i=1;i<=(N<<1|1);i++) if(!flag[i]) getfa(i); 90 int x0=rd(); 91 double mm=inf;int mi=0;h[0]=-inf; 92 for(i=1;i<=N;i++){ 93 ll d1=0,d2=0; 94 getdis(d1,d2,i<<1,x0); 95 if(d2==0&&mm==inf&&h[mi]<h[i]) mi=i; 96 else if(d2!=0){ 97 double r=1.0*d1/d2; 98 if(r<mm||(r==mm&&h[mi]<h[i])) mm=r,mi=i; 99 } 100 } 101 printf("%d\n",mi); 102 103 M=rd(); 104 for(i=1;i<=M;i++){ 105 ll d1=0,d2=0; 106 int a=rd();ll b=rd(); 107 getdis(d1,d2,a<<1,b); 108 printf("%lld %lld\n",d1,d2); 109 } 110 return 0; 111 }