70分做法:

先预处理出所有点的最近和次近(O(n^2)一遍就OK)

然后暴力求出每个解(O(nm))

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 0x3fffffff
using namespace std;
int n,x,rech=0x3fffffff,rec,s,m;
double ans=0x3fffffff;
struct Path{int to,weight,to2,weight2;void init(){weight=inf,weight2=inf,to=-1,to2=-1;}}path[100050];
struct Node{int position,height;}node[100050];
bool cmp(Node a,Node b){return a.height<b.height;}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
node[i].position=i;
scanf("%d",&node[i].height);
}
for(int i=1;i<=n;i++){
path[i].init();
for(int j=i+1;j<=n;j++){
if(path[i].weight2>abs(node[j].height-node[i].height)){
path[i].weight2=abs(node[j].height-node[i].height);
path[i].to2=node[j].position;
}
else if(path[i].weight2==abs(node[j].height-node[i].height)&&node[j].height<node[i].height){
path[i].to2=node[j].position;
}
if(path[i].weight2<path[i].weight){
swap(path[i].weight2,path[i].weight);
swap(path[i].to,path[i].to2);
}
else if(path[i].weight2==path[i].weight&&node[j].height<node[i].height){
swap(path[i].to,path[i].to2);
}
}
}
scanf("%d",&x);
for(int i=1;i<=n;i++){
int wei1=0,wei2=0,f=1;
for(int j=i;;){
if(f){
if(wei1+wei2+path[j].weight2<=x)
wei2+=path[j].weight2;
else break;
j=path[j].to2;
}
else{
if(wei1+wei2+path[j].weight<=x)
wei1+=path[j].weight;
else break;
j=path[j].to;
}
f^=1;
}
if(wei1&&(ans>1.0*wei2/wei1||(ans==1.0*wei2/wei1&&rech<node[i].height))){
ans=1.0*wei2/wei1;
rec=i;
rech=node[i].height;
}
}
printf("%d\n",rec);
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&s,&x);
int wei1=0,wei2=0,f=1;
for(int j=s;;){
if(f){
if(wei1+wei2+path[j].weight2<=x)
wei2+=path[j].weight2;
else break;
j=path[j].to2;
}
else{
if(wei1+wei2+path[j].weight<=x)
wei1+=path[j].weight;
else break;
j=path[j].to;
}
f^=1;
}
printf("%d %d\n",wei2,wei1);
}
}

100分做法:

先用set 从后向前插入 ,取出左边两个点和右边两个点(如果有的话),排个序。

O(nlogn)求出最近和次近。

然后呢 用倍增求距离

g[i][j]表示从i出发走2^j轮到的地方

f[i][j][0]表示从i出发走2^j轮A走了多少

f[i][j][1]表示从i出发走2^j轮B走了多少

预处理出走一轮到哪儿

g[i][0]=edge[edge[i].to2].to;

f[i][0][0]=edge[i].weight2;

f[i][0][1]=edge[edge[i].to2].weight;



倍增就好了…

g[i][j]=g[g[i][j-1]][j-1];

f[i][j][0]=f[g[i][j-1]][j-1][0]+f[i][j-1][0];

f[i][j][1]=f[g[i][j-1]][j-1][1]+f[i][j-1][1];

//By SiriusRen
#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
int n,xx,x,m,g[100050][20],f[100050][20][2],rech,rec;
double ans=0x3fffffff;
struct Node{int height,position;}node[100050];
struct Node2{int height,Short,position;}jy;
struct Edge{int to,to2,weight,weight2;void init(){weight=weight2=0x3fffffff;}}edge[100050];
set<Node>s;set<Node2>p;
bool operator < (Node a,Node b){return a.height<b.height;}
bool operator < (Node2 a,Node2 b){
if(a.Short!=b.Short)return a.Short<b.Short;
else return a.height<b.height;
}
void init(){
for(int i=n;i>=1;i--){
p.clear();edge[i].init();
s.insert(node[i]);
set<Node>::iterator it=s.find(node[i]),it2=it;
if((++it)!=s.end()){
jy.height=(*it).height;
jy.position=(*it).position;
jy.Short=abs((*it).height-node[i].height);
p.insert(jy);
}
else goto deal1;
if((++it)!=s.end()){
jy.height=(*it).height;
jy.position=(*it).position;
jy.Short=abs((*it).height-node[i].height);
p.insert(jy);
}
deal1:if(it2==s.begin())goto deal;
if((--it2)==s.begin()){
jy.height=(*it2).height;
jy.position=(*it2).position;
jy.Short=abs((*it2).height-node[i].height);
p.insert(jy);
goto deal;
}
else
{
jy.height=(*it2).height;
jy.position=(*it2).position;
jy.Short=abs((*it2).height-node[i].height);
p.insert(jy);
}
it2--;
jy.height=(*it2).height;
jy.position=(*it2).position;
jy.Short=abs((*it2).height-node[i].height);
p.insert(jy);
deal:set<Node2>::iterator itp=p.begin();
if(itp!=p.end()){
edge[i].weight=(*itp).Short;
edge[i].to=(*itp).position;
if((++itp)!=p.end()){
edge[i].weight2=(*itp).Short;
edge[i].to2=(*itp).position;
}
}
}
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&node[i].height);
node[i].position=i;
}
init();
for(int i=1;i<=n;i++){
g[i][0]=edge[edge[i].to2].to;
f[i][0][0]=edge[i].weight2;
f[i][0][1]=edge[edge[i].to2].weight;
}
for(int j=1;j<=18;j++){
for(int i=1;i<=n;i++){
g[i][j]=g[g[i][j-1]][j-1];
f[i][j][0]=f[g[i][j-1]][j-1][0]+f[i][j-1][0];
f[i][j][1]=f[g[i][j-1]][j-1][1]+f[i][j-1][1];
}
}
scanf("%lld%lld",&x,&m);
for(int i=1;i<=n;i++){
int wei1=0,wei2=0,S=i,temp=x;
for(int j=17;j>=0;j--){
if(temp>=f[S][j][0]+f[S][j][1]&&g[S][j]){
wei1+=f[S][j][0];
wei2+=f[S][j][1];
temp=temp-(f[S][j][0]+f[S][j][1]);
S=g[S][j];
}
}
if(temp>=edge[S].weight2&&edge[S].to2){
temp-=edge[S].weight2;
wei1+=edge[S].weight2;
}
if(wei2&&(ans>1.0*wei1/wei2||(ans==1.0*wei1/wei2&&rech<node[i].height))){
rech=node[i].height;
rec=i;
ans=1.0*wei1/wei2;
}
}
printf("%lld\n",rec);
for(int i=1;i<=m;i++){
scanf("%lld%lld",&xx,&x);
int wei1=0,wei2=0,S=xx,temp=x;
for(int j=17;j>=0;j--){
if(temp>=f[S][j][0]+f[S][j][1]&&g[S][j]){
wei1+=f[S][j][0];
wei2+=f[S][j][1];
temp=temp-(f[S][j][0]+f[S][j][1]);
S=g[S][j];
}
}
if(temp>=edge[S].weight2&&edge[S].to2){
temp-=edge[S].weight2;
wei1+=edge[S].weight2;
}
printf("%lld %lld\n",wei1,wei2);
}
}

NOIP2012 T3开车旅行 set+倍增的更多相关文章

  1. 【NOIP2012】开车旅行(倍增)

    题面 Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i的海拔高度为Hi,城市 ...

  2. Luogu 1081 【NOIP2012】开车旅行 (链表,倍增)

    Luogu 1081 [NOIP2012]开车旅行 (链表,倍增) Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已 ...

  3. 2012Noip提高组Day1 T3 开车旅行

    题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...

  4. 【vijos1780】【NOIP2012】开车旅行 倍增

    题目描述 有\(n\)个城市,第\(i\)个城市的海拔为\(h_i\)且这\(n\)个城市的海拔互不相同.编号比较大的城市在东边.两个城市\(i,j\)之间的距离为\(|h_i-h_j|\) 小A和小 ...

  5. NOIP2012开车旅行 【倍增】

    题目 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为Hi,城市 i 和城 ...

  6. $Noip2012\ Luogu1081$ 开车旅行 倍增优化$ DP$

    Luogu Description Sol 1.发现对于每个城市,小A和小B的选择是固定的,可以预处理出来,分别记为ga[],gb[] 2.并且,只要知道了出发城市和出发天数,那么当前城市和小A,小B ...

  7. vijos P1780 【NOIP2012】 开车旅行

    描述 小\(A\)和小\(B\)决定利用假期外出旅行,他们将想去的城市从\(1\)到\(N\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为 ...

  8. noip2012 P1081 开车旅行

    小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为Hi,城市 i 和城市 j ...

  9. luogu1081 开车旅行 树上倍增

    题目大意 小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市i 的海拔高度为Hi,城市i 和城市j 之间的距离 ...

随机推荐

  1. 杂项-快捷键:Google浏览器常用快捷键

    ylbtech-杂项-快捷键:Google浏览器常用快捷键 1.返回顶部 1. Google浏览器,是一个由Google(谷歌)公司开发的开放原始码网页浏览器.该浏览器是基于其他开放原始码软件所撰写, ...

  2. oracle故障处理之删除大表空间hang住

    背景 数据库分区表数据越来越大,需要对过期话的数据进行迁移,以及大的分区表需要进行数据的清理和删除,达到释放磁盘空间的目的. 问题说明 环境:linux 6.X 数据库:oracle 11.2.0.4 ...

  3. caffe study- AlexNet 之算法篇

    在机器学习中,我们通常要考虑的一个问题是如何的“以偏概全”,也就是以有限的样本或者结构去尽可能的逼近全局的分布.这就要在样本以及结构模型上下一些工夫. 在一般的训练任务中,考虑的关键问题之一就是数据分 ...

  4. 微信公众号测试账号-redirect_uri域名与后台配置不一致,错误代码:10003

    微信公众号测试账号-redirect_uri域名与后台配置不一致,错误代码:10003 进入公众平台测试账号. 登录公众账号--"开发者中心"--"公众平台测试账号&qu ...

  5. Java NIO(五)套接字通道

    Socket通道 Socket通道和文件通道有着不一样的特征: Socket通道类可以运行于非阻塞模式,并且是可选的.这两个特征可以激活大程序(如网络服务和中间件组件)巨大的可伸缩性和灵活性,因此再也 ...

  6. IE8不支持响应式设计解决方法

    下载并引入 respond.js 即可 为了针对IE8应用这段脚本,需要针对IE8的条件注释 <!--[if lt IE 9]> --- <! [endif]--> 为了不让并 ...

  7. Sentry: Python 实时日志平台

    Links https://docs.getsentry.com/on-premise/quickstart/ https://docs.getsentry.com/on-premise/server ...

  8. python包管理(distutils、easy_install、pip、setup.py/requirements.txt、wheel)

    distutils.distutils2 distutils是 python 标准库的一部分,2000年发布.使用它能够进行 python 模块的 安装 和 发布. distutils2 被设计为 d ...

  9. WCF(一)控制台寄宿

    WCF是微软开发的一款通信框架.具有跨平台跨操作系统的特点,所以,WCF一般用于开发第三方接口或者在分布式系统用做数据交互. WCF三要素分别是地址(Address).绑定(Binding).契约(C ...

  10. WebApp开发技巧大全

    1.开发成本较低使用web开发技术就可以轻松的完成web app的开发 2.升级较简单升级不需要通知用户,在服务端更新文件即可,用户完全没有感觉 3.维护比较轻松和一般的web一样,维护比较简单,它其 ...