【NOIP2012】开车旅行

给你一囗甜甜゛ 提交于 2019-11-28 20:56:28

题面

https://www.luogu.org/problem/P1081

题解

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<set>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cassert>

using namespace std;

const long long INF=100000000000LL;

struct city{
  int num;
  long long h;
  bool operator < (const city rhs) const {
    return h<rhs.h;
  }
};

set<city> s;
vector <int> son[205000];
int fa[205000],f[205000][20],n,m,p;
long long h[105000],sum1[205000],sum2[205000],sum0[205000],x0;
bool vis[205000];
double val;

long long abq(long long x){
  if (x>=0) return x; else return -x;
}

bool smaller(int x,city yuan,city now){
  if (abq(now.h-h[x])<abq(yuan.h-h[x])||
    (abq(now.h-h[x])==abq(yuan.h-h[x])&&now.h<yuan.h)) return true; else return false;
}

double fabs(double x){
  if (x>=0) return x; else return -x;
}
long long hei(int x){
  if (x>n) return h[x-n]; else return h[x];
}

bool dengyu(double x,double y){
  if (fabs(x-y)<=1e-6) return true; else return false;
}

set<city>::iterator it,pit,ppit,sit,ssit,nul;
city mym,smym;

void maketree(int x){
  int i,l=son[x].size();
  if (fa[x]!=-1) f[x][0]=fa[x]; else f[x][0]=x;
  for (i=1;i<=19;i++) f[x][i]=f[f[x][i-1]][i-1];
  if (fa[x]!=-1){
    sum0[x]=sum0[fa[x]]+abq(hei(fa[x])-hei(x));
    if (x>n) sum1[x]=sum1[fa[x]]+abq(hei(fa[x])-hei(x)),sum2[x]=sum2[fa[x]];
        else sum2[x]=sum2[fa[x]]+abq(hei(fa[x])-hei(x)),sum1[x]=sum1[fa[x]];
  }
  for (i=0;i<l;i++) maketree(son[x][i]);
}

int dfs(int x){
  int i;
  long long sum=0;
  for (i=19;i>=0;i--) if (sum0[x]-sum0[f[x][i]]+sum<=x0) {
    sum+=sum0[x]-sum0[f[x][i]];
    x=f[x][i];
  }
  return x;
}

set<city> empty;

int main(){
  int i,ss;
  city now;
  nul=empty.begin();
  scanf("%d",&n);
  for (i=1;i<=n;i++) scanf("%lld",&h[i]);
  for (i=n;i>=1;i--) {
    now=(city){i,h[i]};
    s.insert(now);
    it=s.lower_bound(now);
    ppit=pit=sit=ssit=it;
    if (pit!=s.begin()) {
      pit--; ppit--;
      if (ppit!=s.begin()) ppit--; else ppit=nul;
    }
    else ppit=pit=nul;
    ++sit; ++ssit;
    if (sit==s.end()) ssit=sit=nul; 
    else {
      ++ssit;
      if (ssit==s.end()) ssit=nul;
    }
    mym=(city){2*n+1,INF};
    smym=(city){2*n+1,INF};
    if (ppit!=nul && smaller(i,mym,*ppit)) smym=mym,mym=*ppit; 
        else if (ppit!=nul && smaller(i,smym,*ppit)) smym=*ppit;
    if (pit!=nul  && smaller(i,mym,*pit)) smym=mym,mym=*pit; 
        else if (pit!=nul && smaller(i,smym,*pit)) smym=*pit;
    if (sit!=nul  && smaller(i,mym,*sit)) smym=mym,mym=*sit; 
        else if (sit!=nul && smaller(i,smym,*sit)) smym=*sit;
    if (ssit!=nul && smaller(i,mym,*ssit)) smym=mym,mym=*ssit; 
        else if (ssit!=nul && smaller(i,smym,*ssit)) smym=*ssit;
    if (mym.h!=INF) fa[i]=n+mym.num,son[n+mym.num].push_back(i); else fa[i]=-1;
    if (smym.h!=INF) fa[n+i]=smym.num,son[smym.num].push_back(n+i); else fa[n+i]=-1;
  }
  scanf("%lld",&x0);
  scanf("%d",&m);
  for (i=2*n;i>=1;i--) if (fa[i]==-1) {
    sum0[i]=sum1[i]=sum2[i]=0;
    maketree(i);
  }
  val=987654322*987654321LL; p=2*n+1;
  h[p]=987654322*987654321LL;
  double s1,s2,ans;
  int end;
  for (i=n+1;i<=2*n;i++) {
    end=dfs(i);
    if (end!=i) {
      s1=sum1[i]-sum1[end]; s2=sum2[i]-sum2[end];
      if (s2==0) ans=INF; else ans=s1/s2;
      if (ans<val || (dengyu(ans,val)&& h[i-n]>h[p])) val=ans,p=i-n;
    }
  }
  printf("%d\n",p);
  for (i=1;i<=m;i++) {
    scanf("%d %lld",&ss,&x0);
    end=dfs(n+ss);
    printf("%lld %lld\n",sum1[n+ss]-sum1[end],sum2[n+ss]-sum2[end]);
  }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!