noip 2012 开车旅行

/*考场上写的暴力 40分钟70分*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define base 1000000000
#define maxn 100010
#define ll long long
using namespace std;
ll n,m,h[maxn],X,A[maxn],B[maxn],st,ans;
bool falg;
double mii=base;
ll init()
{
    ll x=0,f=1;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}
ll Abs(ll a)
{
    return a<0?-a:a;
}
void Get_AB()
{
    for(int i=1;i<=n;i++)
      {
          ll mxx,mx,mxxh,mxh,kxx=0,kx=0;mxx=mx=0x7fffffff;
          for(int j=i+1;j<=n;j++)
            {
                ll C=Abs(h[i]-h[j]);
                if(C<mxx||(C==mxx&&h[j]<mxxh))
              mx=mxx,mxx=C,mxh=mxxh,mxxh=h[j],kx=kxx,kxx=j;
                else if((C==mxx&&h[j]>=mxxh)||C<mx||(C==mx&&h[j]<mxh))
              mx=C,mxh=h[j],kx=j;
          }
        A[i]=kx;B[i]=kxx;
      }
}
void Dfs(ll now,ll who,ll As,ll Bs,ll limit,ll S)
{
    if(falg)return;ll s1=0,s2=0;double tmp;
    if(!who)s1=As+Abs(h[now]-h[A[now]]),S+=Abs(h[now]-h[A[now]]);
    if(who)s2=Bs+Abs(h[now]-h[B[now]]),S+=Abs(h[now]-h[B[now]]);
    if(S>limit||(!who&&A[now]==0)||(who&&B[now]==0))
      {
          if(!Bs)tmp=base;
          else tmp=double(As)/double(Bs);
          if(tmp<mii||(tmp==mii&&h[st]>h[ans]))
            ans=st,mii=tmp;
          falg=1;return ;
      }
    if(!who&&s1<=limit)Dfs(A[now],!who,s1,Bs,limit,S);if(falg)return;
    if(who&&s2<=limit)Dfs(B[now],!who,As,s2,limit,S);if(falg)return;
    if(!Bs)tmp=base;
    else tmp=double(As)/double(Bs);
    if(tmp<mii||(tmp==mii&&h[st]>h[ans]))
      ans=st,mii=tmp;
    falg=1;return ;
}
void dfs(ll now,ll who,ll As,ll Bs,ll limit,ll S)
{
    if(falg)return;ll s1=0,s2=0;
    if(!who)s1=As+Abs(h[now]-h[A[now]]),S+=Abs(h[now]-h[A[now]]);
    if(who)s2=Bs+Abs(h[now]-h[B[now]]),S+=Abs(h[now]-h[B[now]]);
    if(S>limit||(!who&&A[now]==0)||(who&&B[now]==0))
      {
        cout<<As<<" "<<Bs<<endl;
        falg=1;return;
      }
    if(!who&&s1<=limit)dfs(A[now],!who,s1,Bs,limit,S);if(falg)return;
    if(who&&s2<=limit)dfs(B[now],!who,As,s2,limit,S);if(falg)return;
    cout<<As<<" "<<Bs<<endl;
    falg=1;return;
}
int main()
{
    n=init();int x,s;
    for(int i=1;i<=n;i++)
      {
          x=init();h[i]=x+base;
      }
    Get_AB();X=init();
    for(int i=1;i<=n;i++)
      falg=0,st=i,Dfs(i,0,0,0,X,0);
    cout<<ans<<endl;
    m=init();
    for(int i=1;i<=m;i++)
      {
          s=init();x=init();
          falg=0;dfs(s,0,0,0,x,0);
      }
    return 0;
} 
/*
暴力的复杂度是n*n的
首先预处理每个点的最短次短距离就Tle了
这里我们借助set O n 的解决这个问题
然后对于每个询问 利用倍增 logn的实现就不超时了
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<cmath>
#define base 100000000000//大大大大大
#define maxn 100010
#define ll long long
using namespace std;
ll n,m,X,A[maxn],B[maxn],As[maxn],Bs[maxn],ans;
ll d[maxn][25],f[maxn][25][2];
double mii=base;
struct point
{
    ll o,hi;
    bool operator < (const point & a) const
      {
          return hi<a.hi;
      }
}p[maxn];
set<point>s;
set<point>::iterator pi;
ll init()
{
    ll x=0,f=1;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}
ll abs(ll a)
{
    return a<0?-a:a;
}
void Add(point x,point y)
{
    if(!B[x.o])
    {
        B[x.o]=y.o;
        Bs[x.o]=abs(x.hi-y.hi);
    }
    else if(abs(x.hi-y.hi)<Bs[x.o]||(abs(x.hi-y.hi)==Bs[x.o]&&y.hi<p[B[x.o]].hi))
    {
        A[x.o]=B[x.o];
        As[x.o]=Bs[x.o];
        B[x.o]=y.o;
        Bs[x.o]=abs(x.hi-y.hi);
    }
    else if(abs(x.hi-y.hi)<As[x.o]||(abs(x.hi-y.hi)==As[x.o]&&y.hi<p[A[x.o]].hi))
    {
        A[x.o]=y.o;
        As[x.o]=abs(x.hi-y.hi);
    }
    else if(!A[x.o])
    {
        A[x.o]=y.o;
        As[x.o]=abs(x.hi-y.hi);
    }
    return;
}
void Get_AB()
{
    for(int i=n;i>=1;i--)
      {
          s.insert(p[i]);
          pi=s.find(p[i]);
          if(pi!=s.begin())
            {
                pi--;Add(p[i],*pi);
                if(pi!=s.begin())
                {
                    pi--;Add(p[i],*pi);pi++;
              }
            pi++;
          }
        if((++pi)!=s.end())
          {
              Add(p[i],*pi);
                if((++pi)!=s.end())
                  Add(p[i],*pi);
            pi--;
          }
        pi--;
      }
}
void Query(int st,ll limit,ll & sa,ll & sb)
{
    for(int i=20;i>=0;i--)
      if(f[st][i][1]+f[st][i][0]<=limit&&d[st][i])
        {
          sa+=f[st][i][0];sb+=f[st][i][1];
          limit-=(f[st][i][1]+f[st][i][0]);st=d[st][i];
        }
    if(A[st]&&As[st]<=limit)
      sa+=As[st];
}
int main()
{
    n=init();
    for(int i=1;i<=n;i++)
      {
        p[i].hi=init();p[i].o=i;
      }
    Get_AB();
    for(int i=1;i<=n;i++)
    {
        d[i][0]=B[A[i]];
        f[i][0][0]=As[i];
        f[i][0][1]=Bs[A[i]];
    }
    for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++)
        {
            d[i][j]=d[d[i][j-1]][j-1];
            f[i][j][0]=f[i][j-1][0]+f[d[i][j-1]][j-1][0];
            f[i][j][1]=f[i][j-1][1]+f[d[i][j-1]][j-1][1];
        }
    X=init();
    for(int i=1;i<=n;i++)
      {
          ll sa=0,sb=0;double tmp;
          Query(i,X,sa,sb);
          if(!sb)tmp=base;
          else tmp=double(sa)/double(sb);
          if(tmp<mii||(tmp==mii&&p[i].hi>p[ans].hi))
            ans=i,mii=tmp;
      }
    cout<<ans<<endl;
    m=init();int st;
    for(int i=1;i<=m;i++)
      {
          st=init();X=init();
          ll sa=0,sb=0;
          Query(st,X,sa,sb);
          cout<<sa<<" "<<sb<<endl;
      }
    return 0;
} 
时间: 2024-10-29 19:08:45

noip 2012 开车旅行的相关文章

codevs 1199 开车旅行 2012年NOIP全国联赛提高组

1199 开车旅行 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i的海拔高度为Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即d[i, j] = |Hi − Hj|. 旅行过程中,小A 和小B轮流开

noip2012 开车旅行

P1081 开车旅行 139通过 484提交 题目提供者洛谷OnlineJudge 标签倍增2012NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录 题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi− Hj|. 旅行过程中,小

[NOIP2012] 提高组 洛谷P1081 开车旅行

题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi− Hj|. 旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次.他们计划 选择一个城市 S 作为起点,一直向东行驶,并且最多行驶 X 公里就结束旅行.小 A 和小 B

NOIP 2012 题解

[D1T1vigenere密码] P1778vigenere密码 Accepted 标签:[显示标签] 描述 16世纪法国外交家Blaise de Vigenère设计了一种多表密码加密算法--Vigenère密码.Vigenère密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用M表示:称加密后的信息为密文,用C表示:而密钥是一种参数,是将明文转换为密文或将密文转换为明文的算法中输入的数据,记为k. 在Vigenère

开车旅行

洛谷P1081 开车旅行  NOIP 2012 提高组 第一天 第三题 题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi− Hj|. 旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次.他们计划 选择一个城市 S 作

【NOIP2012】开车旅行

题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi? Hj|. 旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次.他们计划 选择一个城市 S 作为起点,一直向东行驶,并且最多行驶 X 公里就结束旅行.小 A 和小 B

洛谷P1081 开车旅行

P1081 开车旅行 152通过 524提交 题目提供者洛谷OnlineJudge 标签倍增NOIp提高组2012 难度省选/NOI- 提交该题 讨论 题解 记录 最新讨论 我前排提醒一下 题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi−

习题:开车旅行(倍增+预处理)

开车旅行(NOIP提高组2012) [描述]小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市i 的海拔高度为Hi,城市i 和城市j 之间的距离d[i,j]恰好是这两个城市海拔高度之差的绝对值,即d[i,j] = |Hi - Hj|.旅行过程中,小A和小B轮流开车,第一天小A开车,之后每天轮换一次.他们计划选择一个城市S作为起点,一直向东行驶,并且最多行驶X公里就结束旅行.小A和小B的驾驶风格不同,小B总是

NOIP 2012 Day1

tags: NOIP 模拟 倍增 高精 Python categories: 信息学竞赛 总结 Luogu P1079 Vigenère 密码 Solution 表示并不是很懂其他人发的题解. 我是这么想的, 既然是题目要求用密文转明文而且转换规则一定的, 所以就可以用明文转密文的逆过程来完成. 首先要搞明白明文是怎么变成密文的, 通过这个表可以观察到, 如果明文的一个字符是 ch1 ,密钥为 ch2 , 那么密文 ch3 对应的就是 ch1 在字母表中偏移 |ch2| 位, 例如 \(\tex