zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",d1,d2);
    109     }
    110     return 0;
    111 }
  • 相关阅读:
    五秒自动刷新页面
    浅析MySQL中exists与in的使用 (写的非常好)
    基于shiro授权过程
    shiro认证
    jsp中<c:if>与<s:if>的区别
    链表数据结构相关
    队列Queue中add()和offer()的区别?
    Java中有几种线程池?
    解决idea使用jstl标签报错和不自动提示
    事务
  • 原文地址:https://www.cnblogs.com/Ressed/p/9735538.html
Copyright © 2011-2022 走看看