hdu

来源:互联网 发布:中国国防数据 编辑:程序博客网 时间:2024/05/19 10:15

HDU - 6136

解法一
第一种解法比较直观,最初始状态环上有 n个人,第一次淘汰发生必然是环上相邻的两个人相撞。注意到第一个被淘汰的人不会对后续过程有任何影响,如果我们能找出谁是第一个被淘汰的,直接把这个人从初始状态中删除,就能把问题变成一个只有 n1个人的子问题,这个子问题和原问题有相同的答案。
于是我们可以用一个堆维护环上所有相邻人相遇的时间,从中取出最小值,就能找到第一个被淘汰的人,这个人删除后,原本不相邻的两个人就相邻了,同样求出他们的相遇时间,加入堆中,重复执行这一过程,直到找到最后一个被淘汰的人为止。算法复杂度 O(nlogn)O(nlogn)

#include<bits/stdc++.h>#define list lllusing namespace std;const int MAXN = 1E5+10;int n,l;struct Car{    int d,v,i;    friend bool operator <  (const Car& a,const Car &b)    {        return a.d<b.d;    }} car[MAXN];struct List{    int pre,next;} list[MAXN];void del(int i){    if(list[i].pre!=-1) list[list[i].pre].next=list[i].next;    if(list[i].next!=2*n) list[list[i].next].pre=list[i].pre;}bool vis[MAXN];struct Status{    int a,b;//约定b是在a的顺时针方向上的,也就是速度的正方向    long long int d,v;    friend bool operator < (const Status &a,const Status &b)    {        return a.d*b.v>b.d*a.v;    }};struct Fenshu{    long long int fenzi,fenmu;    void reduce()    {        long long int gcd = __gcd(fenzi,fenmu);        fenzi/=gcd;        fenmu/=gcd;    }};Status check(int a,int b){    Status status= {a,b};    status.d=car[b].d-car[a].d;    if(status.d<0) status.d+=l;//如果距离是负数说明是绕了一圈    status.v=0;    if(car[a].v>=0&&car[b].v<=0)    {        status.v=abs(car[a].v)+abs(car[b].v);    }    else if(car[a].v>=0&&car[b].v>=0)    {        if(car[a].v>car[b].v)        {            status.v=car[a].v-car[b].v;        }    }    else if(car[a].v<=0&&car[b].v<=0)    {        if(abs(car[a].v)<abs(car[b].v))        {            status.v=abs(car[b].v)-abs(car[a].v);        }    }    //除了上面那几种情况之外,ab都不可能通过这段status.d圆弧相遇    return status;}int main(){    if (fopen("in.txt", "r") != NULL)    {        freopen("in.txt", "r", stdin);        //freopen("out.txt", "w", stdout);    }    int t;    cin>>t;    while(t--)    {        memset(vis,false,sizeof vis);        scanf("%d%d",&n,&l);        for(int i=0; i<n; i++)        {            scanf("%d",&car[i].d);        }        for(int i=0; i<n; i++)        {            scanf("%d",&car[i].v);        }        for(int i=0; i<n; i++)        {            car[i].i=i;        }        sort(car,car+n);        for(int i=0; i<n; i++)        {            list[i].pre=i-1;            list[i].next=i+1;        }        list[0].pre=n-1;        list[n-1].next=0;        priority_queue<Status> que;        for(int i=0; i<n; i++)        {            Status status = check(i,list[i].next);            if(status.v)                que.push(status);        }        Fenshu ans;        int cnt=0;        while(que.size())        {            Status top = que.top();            que.pop();            if(vis[top.a]||vis[top.b])//如果有一个是不存在了的,那么就应该不进行下面的计算            {                bool dela=false,delb=false;                if(vis[top.a])                {                    dela=true;                }                if(vis[top.b])                {                    delb=true;                }                if(dela==false&&delb==true)//重新考虑没死的两边新的情况                {                    Status status = check(top.a,list[top.a].next);                    if(status.v)                        que.push(status);                }                if(dela==true&&delb==false)                {                    Status status = check(list[top.b].pre,top.b);                    if(status.v)                        que.push(status);                }                continue;            }            ans={top.d,top.v};            int live,dead;            if(car[top.a].i>car[top.b].i)            {                dead=top.b;                live=top.a;            }            else            {                dead=top.a;                live=top.b;            }            vis[dead]=true;            del(dead);            Status status;            if(live==top.a)                status=check(live,list[live].next);            else status=check(list[live].pre,live);            if(status.v)                que.push(status);        }        ans.reduce();        printf("%lld/%lld\n",ans.fenzi,ans.fenmu);    }    return 0;}