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 }

 

posted @ 2018-10-01 19:53  Ressed  阅读(179)  评论(0编辑  收藏  举报