【NOIP2012】开车旅行

匿名 (未验证) 提交于 2019-12-02 23:56:01

题面

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]);   } }

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