1. 程式人生 > >[Educational Round 10][Codeforces 652F. Ants on a Circle]

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

cli != cmp style 沒有 情況 spa mes view

題目連接: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? :\n); return 0; }
View Code

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