• [Educational Round 10][Codeforces 652F. Ants on a Circle]


    题目连接:652F - Ants on a Circle

    题目大意:(n)个蚂蚁在一个大小为(m)的圆上,每个蚂蚁有他的初始位置及初始面向,每个单位时间蚂蚁会朝着当前面向移动一个单位长度,在遇到其它蚂蚁时会立刻掉头。求经过(t)个单位时间后每一个蚂蚁的所在位置

    题解:首先可以发现,最终答案其实是在不考虑碰撞下得出答案的一个排列,而且蚂蚁们的相对位置是不会改变的。所以如果求出了其中任意一个蚂蚁的位置,就能求出最终的答案。

       为了方便起见,先默认所有蚂蚁的位置是按升序排的,且第一个蚂蚁的位置为(0)

       对于碰到同伴就掉头这个情况,可以换一种视角来考虑,即碰到同伴时,不掉头,而是交换相遇两蚂蚁的编号,这样子做从结果上看二者并没有差别

       对于所有蚂蚁,就以第一个蚂蚁为例,假设其初始面向是向右,则当他遇到其他蚂蚁时,会和他右边的蚂蚁交换编号。又由蚂蚁们的相对位置不变,可以得出他右边蚂蚁的编号始终是比他自己大(1)的,因此可以得出,每次碰撞带来的后果就是使其编号加一。又因为在走过一圈后,所有的蚂蚁都回到了初始的位置,且面向未发生改变,所以每一圈编号的变化量是固定的。所以可以得出在经过(t)时间后,该蚂蚁的编号发生了多少改变,并与该蚂蚁的最终位置相匹配即可。

       这种做法存在一种问题就是,若这个蚂蚁的最终位置与其他蚂蚁的位置重复,则无法确定他具体在哪个编号上。这时可以找出那个和该蚂蚁终点相同的蚂蚁,再做一遍相同的操作,比较下两个蚂蚁的编号就好了。

       虽然代码看上去很长,但实际上(f**k())里的内容都是照抄下面的东西,写起来还是挺简单的

    #include<bits/stdc++.h>
    using namespace std;
    #define N 600001
    #define LL long long
    #define mp make_pair
    LL n,m,t,d,x,mn,cnt,b[N],r[N],r2[N],f[N],ans[N];
    pair<LL,LL>a[N];
    bool cmp(LL x,LL y){return a[x]<a[y];}
    bool cmp2(LL x,LL y){return f[x]<f[y];}
    LL get()
    {
        char ch=getchar();
        while(ch!='L' && ch!='R')
          ch=getchar();
        return ch=='L'?-1:1;
    }
    void fuck()
    {
        for(LL i=0;i<n;i++)
          f[i]=(a[i].first+(t%m)*(m+a[i].second))%m;
        LL X=0;
        for(LL i=0;i<n;i++)
          if(f[i]==f[0])X=i;
        LL c=a[X].first;
        for(LL i=0;i<n;i++)
          a[i].first=(a[i].first+m-c)%m;
        sort(a,a+n);
        cnt=0;
        for(LL i=0;i<n;i++)
          if(a[i].second!=a[0].second)
            {
            b[cnt++]=a[i].first;
            b[cnt++]=a[i].first+m;
            }
        sort(b,b+cnt);
        for(LL i=0;i<n;i++)
          f[i]=(a[i].first+(t%m)*(m+a[i].second))%m;
        LL dd=lower_bound(b,b+cnt,f[0]*2)-b;
        if(b[dd]==f[0]*2 && a[0].second>0)dd++;
        if(a[0].second<0 && f[0])dd=cnt-dd;
        dd+=cnt*((t/m)%n),dd%=n;
        if(a[0].second<0)dd=(n-dd)%n;
        for(LL i=0;i<n;i++)
          a[i].first=(a[i].first+c)%m;
        for(LL i=0;i<n;i++)
          f[i]=(a[i].first+(t%m)*(m+a[i].second))%m;
        sort(f,f+n);
        if((d+1)%n==(dd+X)%n && f[x]==f[(x+n-1)%n])x=(x+n-1)%n;
        if(d==(dd+X+1)%n && f[x]==f[(x+1)%n])x=(x+1)%n;
    }
    int main()
    {
        scanf("%I64d%I64d%I64d",&n,&m,&t);
        for(LL i=0;i<n;i++)
          {
          r[i]=r2[i]=i;
          scanf("%I64d",&a[i].first);
          a[i].second=get();
          }
        sort(r,r+n,cmp);
        sort(a,a+n);
        mn=a[0].first;
        for(LL i=0;i<n;i++)
          a[i].first-=mn;
        for(LL i=0;i<n;i++)
          if(a[i].second!=a[0].second)
            { 
            b[cnt++]=a[i].first;
            b[cnt++]=a[i].first+m;
            }
        sort(b,b+cnt);
        for(LL i=0;i<n;i++)
          f[i]=(a[i].first+(t%m)*(m+a[i].second))%m;
        d=lower_bound(b,b+cnt,f[0]*2)-b;
        if(b[d]==f[0]*2 && a[0].second>0)d++;
        if(a[0].second<0 && f[0])d=cnt-d;
        d+=cnt*((t/m)%n),d%=n;
        if(a[0].second<0)d=(n-d)%n;
        sort(r2,r2+n,cmp2);
        sort(f,f+n);
        for(LL i=0;i<n;i++)
          if(r2[i]==0)x=i;
        if(f[x]==f[(x+1)%n] || f[x]==f[(x+n-1)%n])fuck();
        for(LL i=0;i<n;i++)
          ans[r[(d+i)%n]]=f[(x+i)%n];
        for(LL i=0;i<n;i++)
          printf("%I64d%c",(ans[i]+mn-1)%m+1,i<n-1?' ':'
    ');
        return 0;
    }
    View Code
  • 相关阅读:
    Github精选——devops一体化监控平台工具WGCLOUD
    [搬运][中英双语]字体推荐 | 如果你每天都在代码面前,为何不让其变得有趣起来呢?
    【学习笔记】二分图最大匹配 -- 从网络流到匈牙利算法
    【详细揭秘】多重集の交错排列
    支配树口胡
    题解 洛谷 P2388 阶乘之乘
    [eJOI2019]异或橙子 题解
    VBA (Excel) 插入多行的方法 & 算法对比
    20000套免费ppt模板获取攻略
    包你扫到敬业福,集五福活动,福字大全
  • 原文地址:https://www.cnblogs.com/DeaphetS/p/10648138.html
Copyright © 2020-2023  润新知