题面
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 ",p); for (i=1;i<=m;i++) { scanf("%d %lld",&ss,&x0); end=dfs(n+ss); printf("%lld %lld ",sum1[n+ss]-sum1[end],sum2[n+ss]-sum2[end]); } }