zoukankan      html  css  js  c++  java
  • 炮艇大赛之正式赛(单调队列)

    题目描述

    给定一个长度为L的环形赛道, n个人在上面赛艇. 每个人的速度都不相同, 假如为正则顺时针走, 否则逆时针走. 当两个人相遇时, 编号小的那个人就会出局. 当只剩下一个人时, 这个人就获得胜利.(L<=1e9 , n<=1e5)

    问: 多久以后游戏结束.

    #include<bits/stdc++.h>
    using namespace std;
    int read(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int get_gcd(int a,int b){
        if(b==0) return a;
        return get_gcd(b,a%b);
    }
    const int N=1e5+5;
    int n,L;
    struct boat{int w,d,v;}a[N];
    bool cmpd(boat a,boat b){
        return a.d<b.d;
    }
    struct record{
        int id[2];double t;
        inline record(){}
        inline record(int u,int v){
            if(a[u].v>a[v].v) swap(u,v);
            t=(double)((a[u].d-a[v].d+L)%L)/(a[v].v-a[u].v);//相遇时间 
            id[0]=u;id[1]=v;
            if(a[id[0]].w<a[id[1]].w) swap(id[0],id[1]);//id[0]留下,id[1]出局 
        }
        inline int operator <(const record &a) const{return t>a.t;}//从小到大排 
    };
    static int nxt[N],lst[N],del[N]; 
    int main(){
        n=read();L=read();
        for(int i=1;i<=n;i++){
            a[i].w=i;a[i].d=read();
        }
        for(int i=1;i<=n;i++){
            a[i].v=read();
        }
        //因为每次相遇的只能是位置相邻的两人,所以把相邻两人相遇所需要的时间用一个堆维护起来
        sort(a+1,a+n+1,cmpd);
        priority_queue<record> q;
        q.push(record(1,n));
        for(int i=2;i<=n;i++) q.push(record(i,i-1));
        for(int i=1;i<=n;i++) nxt[i]=(i+1)%n==0?n:(i+1)%n;
        for(int i=1;i<=n;i++) lst[i]=(i-1)%n==0?n:(i-1)%n;
        //每次找到最早相遇的两个人,记录其中一人出局,并将新产生的相邻的两人加入堆中
        for(int i=n;i>=3;i--){
            record rec;
            while(1){
                rec=q.top();q.pop();
                int pd=1;
                if(del[rec.id[0]]||del[rec.id[1]]) pd=0;
                if(pd) break;
            }
            del[rec.id[1]]=1;
            nxt[lst[rec.id[1]]]=nxt[rec.id[1]];
            lst[nxt[rec.id[1]]]=lst[rec.id[1]];
            nxt[rec.id[1]]=lst[rec.id[1]]=-1;
            q.push(record(rec.id[0],nxt[rec.id[0]]));
            q.push(record(rec.id[0],lst[rec.id[0]])); //可能在前面也可能在后面产生新的相邻两人 
        }
        record rec;
        while(1){
            rec=q.top();q.pop();
            int pd=1;
            if(del[rec.id[0]]||del[rec.id[1]]) pd=0;
            if(pd) break;
        }
        //得到最后是哪两人相遇
        if(a[rec.id[0]].v>a[rec.id[1]].v) swap(rec.id[0],rec.id[1]); 
        int ans1=(a[rec.id[0]].d-a[rec.id[1]].d+L)%L;
        int ans2=a[rec.id[1]].v-a[rec.id[0]].v;
        if(ans1==0||ans2==0) printf("0
    ");
        else{
            int gcd=get_gcd(ans1,ans2);
            printf("%d/%d",ans1/gcd,ans2/gcd);
        }
        return 0;    
    }
  • 相关阅读:
    黑马程序员_网络编程
    黑马程序员_ 异常
    黑马程序员_面向对象基础
    黑马程序员_循环语句的使用
    黑马程序员_面向对象深入2
    黑马程序员_ JAVA中的多线程
    黑马程序员_JAVA基础知识总结3
    OC-内存管理
    OC-核心语法(3)(分类、SEL、类本质)
    OC-核心语法2-构造方法
  • 原文地址:https://www.cnblogs.com/HarryPotter-fan/p/11303403.html
Copyright © 2011-2022 走看看