zoukankan      html  css  js  c++  java
  • P1081 开车旅行

    P1081 开车旅行

    排序优化+倍增

    其实这道题一开始是一点也没有头绪,知道有高人指点了一下。说并不需要拘束于出发点和路径长度,也就是问题1.2。不过一个是固定路径长度的询问,另一个是给定起点和路径长度的询问。

    所以问题一和问题二是可以使用一个函数解决的,而且对于一个城市来说,在不考虑路程的情况下,路线是一定的。

    然后我们就可以从遍历图变成枚举终点然后判断路程是否合法。

    然后为了加速就可以使用倍增处理

    对于每个城市,我们需要找他的最近点和次近点。O(N^2)会超时,这时候我们就需要优化可以考虑双向链表进行优化。

    我们先按海拔进行排序,然后将标号为1的点拿出来进行处理,显然,只有在链表中的左右相邻的两个的城市(一个方向)才有可能是满足条件的点

    然后再将处理完最近和次近的点在链表中删除(因为路径方向是有序的),这时候标号为2的点就成了标号为1的点,这样就可以了。

    每次询问,使用倍增进行摸♂索

    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    using std::sort;
    using std::abs;
    const int maxn=101000;
    struct node
    {
        int x;
        int y;
        int l,r;
    };
    node city[maxn];
    int pos[maxn];
    long long dis[maxn][2];
    int to[maxn][2];
    int stf[maxn][20];
    long long sta[maxn][20];
    long long stb[maxn][20];
    int n;
    bool compare(const node &a,const node &b)
    {
        return a.y<b.y;
    }
    int read()
    {
        int res=0,f=1;char c=getchar();
        while(c>'9'||c<'0')
        {
            if(c=='-')	f=-1;
            c=getchar();	
        }
        while(c>='0'&&c<='9')
        {
            res=res*10+c-'0';
            c=getchar();
        }
        return res*f;
    }
    void make_dis(int i,int j)
    {
        int a=0x7fffffff,b=0x7fffffff,c=-1,d=-1;
        for(int l=city[j].l,k=1;l>0&&k<=2;l=city[l].l,k++)
        {
            int pas=abs(city[j].y-city[l].y);
            if(city[l].x<city[j].x)	continue;
            if(a>pas||(a==pas&&city[c].y>city[l].y))
            {
                b=a;d=c;
                a=pas;
                c=l;
            }
            else	if(b>pas||(b==pas&&city[d].y>city[l].y))
            {
                b=pas;
                d=l;
            }
        }
        for(int r=city[j].r,k=1;r<=n&&k<=2;r=city[r].r,k++)
        {
            int pas=abs(city[j].y-city[r].y);
            if(city[r].x<city[r].x)	continue;
            if(a>pas||(a==pas&&city[c].y>city[r].y))
            {
                b=a;d=c;
                a=pas;
                c=r;
            }
            else	if(b>pas||(b==pas&&city[d].y>city[r].y))
            {
                b=pas;
                d=r;
            }
        }//不大会写这种东西
        city[city[j].l].r=city[j].r;
        city[city[j].r].l=city[j].l;
        dis[i][0]=(a == 0x7fffffff ? 0 : a);
        dis[i][1]=(b == 0x7fffffff ? 0 : b);
        to[i][0]= ( c == -1 ? 0 : city[c].x );
        to[i][1]= ( d == -1 ? 0 : city[d].x );
    }
    void make_st()
    {
        for(int i=1;i<=n;i++)
        {
            stf[i][0]=to[to[i][1]][0];
            sta[i][0]=dis[i][1];
            stb[i][0]=dis[to[i][1]][0];
        }
        for(int i=1;i<=19;i++)
            for(int j=1;j<=n;j++)
            {
                stf[j][i]=stf[stf[j][i-1]][i-1];
                sta[j][i]=sta[j][i-1]+sta[stf[j][i-1]][i-1];
                stb[j][i]=stb[j][i-1]+stb[stf[j][i-1]][i-1];
            }
    }
    void query(int k,int x,long long &a,long long &b)
    {
        a=0,b=0;
        for(int i=19;i>=0;i--)
        {
            if(!stf[k][i])	continue;
            if(a+b+sta[k][i]+stb[k][i]>x)	continue;
            a+=sta[k][i];
            b+=stb[k][i];
            k=stf[k][i];
        }
        if(a+b+dis[k][1]<=x)
            a+=dis[k][1];
        return ;
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            city[i].x=i;
            city[i].y=read();
        }
        sort(city+1,city+1+n,compare);//按照海拔排序
        for(int i=1;i<=n;i++)
        {
            city[i].l=i-1;
            city[i].r=i+1;
            pos[city[i].x]=i;//链成链表,记录每个城市在链表中的位置
        }
        for(int i=1;i<=n;i++)
            make_dis(i,pos[i]);
        make_st();
        int x=read();
        long long a1=-0x7fffffff,a2=-0x7fffffff;
        long long m1=0,m2=0;
        double minn=0x7fffffff;
        for(int i=1;i<=n;i++)
        {
            long long a,b;
            query(i,x,a,b);
            if(b&&1.0*a/b<minn)
            {
                a2=i;
                minn=1.0*a/b;
                a1=0x7fffffff;
            }
            if(!b&&city[pos[i]].y>a1)
            {
                a1=city[pos[i]].y;
                a2=i;
            }
        }
        printf("%d
    ",a2);
        int m=read(),s;
        for(int i=1;i<=m;i++)
        {
            long long a,b;
            s=read();x=read();
            query(s,x,a,b);
            printf("%lld %lld
    ",a,b);
        }
        return 0;
    }
    
  • 相关阅读:
    PHP数组、函数
    PHP 基本内容
    Swift基础--tableview练习
    iOS 协议delegate分六步
    UI09_UITableView 使用 单例
    css清除浮动float的三种方法总结,为什么清浮动?浮动会有那些影响?一起来$('.float')
    CSS 如何使DIV层水平居中
    HTML转义字符大全
    jQuery选择器总结
    jQuery 学习笔记_01
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/9399245.html
Copyright © 2011-2022 走看看