zoukankan      html  css  js  c++  java
  • LUOGU P1081 开车旅行 (noip 2012)

    传送门

    解题思路

    这道题刚了一下午,主要就刚在set那里了。先写了一个暴力70分。。之后优化预处理,看着大佬神犇们都用的什么双向链表之类的东西,本蒟蒻不会,又懒得手写平衡树,就拿了个set搞了搞,感觉做麻烦了,我开了两个set,一个存正数一个存负数。因为STL只能求后继,然后每次先求最小,删掉再求次小,再加回来。预处理复杂度应该是nlogn,交了一发75,看了看lyd的书才知道要倍增。f[i][j][0/1]表示一共走了2^i天,在j这个城市,轮A/B开车的到达的城市,如果i=1 f[i][j][k]=f[i-1][f[i-1][j][k]][1-k],意思就是走了2天,一人开了一天,所以由另一个人最后开转移来。如果i>1 f[i][j][k]=f[i-1][f[i-1][j][k]][k], 意思是每个人开了偶数天,所以前后两半的最后都是同一个人开,再预处理一个data表示路程,处理方法和f相近,最后卡了卡常。。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<cmath>
    
    using namespace std;
    const int MAXN = 100005;
    typedef long long LL;
    
    inline LL rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    struct Pos{
        int id;
        LL high;
    }pos[MAXN],rev[MAXN];
    
    int n,m,nxt[MAXN][3],x0,st,f[22][MAXN][2];
    LL ans[3],dis[MAXN][3],data[22][MAXN][2][2];
    double K=1e9;
    set<Pos> S,T;
    bool operator <(const Pos &A,const Pos &B){
        return A.high<B.high;
    }
    
    int main(){
    //  freopen("random.txt","r",stdin);
    //  freopen("A.txt","w",stdout);
        n=rd();int lg=log2(n);
        for(register int i=1;i<=n;i++) pos[i].high=rd(),pos[i].id=i;
        for(register int i=n;i;i--){
            rev[i].high=-pos[i].high;rev[i].id=i;
            LL mn1=1e18,mn2=1e18;int p1=-1,p2=-1;Pos A;int flag=0;
            set<Pos>::iterator it=S.lower_bound(pos[i]);
            if(it!=S.end()) {mn1=abs((*it).high-pos[i].high);p1=(*it).id;A=*it;flag=1;}
            it=T.upper_bound(rev[i]);
            if(it!=T.end() && abs(-((*it).high)-pos[i].high)<=mn1){
                mn1=abs(-((*it).high)-pos[i].high);
                p1=(*it).id;A=*it;flag=2;
            }
            Pos B;B.id=A.id;B.high=-A.high;
            if(flag==1) S.erase(A),T.erase(B);
            else if(flag==2) S.erase(B),T.erase(A);
            if(flag){
                it=S.lower_bound(pos[i]);   
                if(it!=S.end()) {mn2=abs((*it).high-pos[i].high);p2=(*it).id;}
                it=T.upper_bound(rev[i]);
                if(it!=T.end() && abs(-((*it).high)-pos[i].high)<=mn2){
                    mn2=abs(-((*it).high)-pos[i].high);
                    p2=(*it).id;
                }
            }
            if(flag==1) S.insert(A),T.insert(B);
            else if(flag==2) S.insert(B),T.insert(A);
            S.insert(pos[i]);T.insert(rev[i]);
            nxt[i][1]=p2,nxt[i][2]=p1;
            dis[i][1]=mn2,dis[i][2]=mn1;
    //      cout<<i<<" "<<nxt[i][2]<<" "<<dis[i][2]<<endl;
            f[0][i][0]=nxt[i][1];
            f[0][i][1]=nxt[i][2];
            data[0][i][0][0]=dis[i][1];
            data[0][i][1][0]=0;
            data[0][i][0][1]=0;
            data[0][i][1][1]=dis[i][2];     
        }
        for(register int i=1;i<=lg;i++)
            for(register int j=1;j<=n;j++)
                for(register int k=0;k<=1;k++){
                    if(i==1){
                        f[1][j][k]=f[0][f[0][j][k]][1-k];
                        data[1][j][k][0]=data[0][j][k][0]+data[0][f[0][j][k]][1-k][0];
                        data[1][j][k][1]=data[0][j][k][1]+data[0][f[0][j][k]][1-k][1];
                        continue;
                    }
                    f[i][j][k]=f[i-1][f[i-1][j][k]][k];
                    data[i][j][k][0]=data[i-1][j][k][0]+data[i-1][f[i-1][j][k]][k][0];
                    data[i][j][k][1]=data[i-1][j][k][1]+data[i-1][f[i-1][j][k]][k][1];
                }
        x0=rd();
        for(register int i=1;i<=n;i++){
            ans[1]=ans[2]=0;int p=i;
            for(register int j=lg;j>=0;j--)
                if(ans[1]+ans[2]+data[j][p][0][0]+data[j][p][0][1]<=x0){
                    ans[1]+=data[j][p][0][0];ans[2]+=data[j][p][0][1];
                    p=f[j][p][0];
                }
            if(ans[2]==0) {if(K==1e9 && pos[i].high>pos[st].high) st=i;continue;}
            if((double)ans[1]/ans[2]<K || ((double)ans[1]/ans[2]==K && pos[i].high>pos[st].high)){
                st=i;
                K=(double)ans[1]/ans[2];
            }
        }
        printf("%d
    ",st);
        m=rd();
        for(register int i=1;i<=m;i++){ 
            LL x=rd(),y=rd();
            ans[1]=ans[2]=0;int p=x;
            for(register int j=lg;j>=0;j--)
                if(ans[1]+ans[2]+data[j][p][0][0]+data[j][p][0][1]<=y){
                    ans[1]+=data[j][p][0][0];ans[2]+=data[j][p][0][1];
                    p=f[j][p][0];
                }
            printf("%lld %lld
    ",ans[1],ans[2]);
        }
        return 0;
    }
  • 相关阅读:
    JAVA消息对话框
    stringbuffer capacity()的疑问
    JAVA确认对话框
    c/c++实现获取NOD32升级账号密码
    复制构造函数(拷贝构造函数)
    使用VC将sqlite3.def转化为sqlite3.lib
    Windows下安装OpenSSL
    java中io与nio的使用
    使用 XStream 把 Java 对象序列化为 XML
    使用 XStream 把 Java 对象序列化为 XML
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676912.html
Copyright © 2011-2022 走看看