【AGC013C】Ants on a Circle 弹性碰撞

题目大意

  一个长度为\(lm\)的环上有\(n\)只蚂蚁,告诉你每只蚂蚁的位置和朝向,每只蚂蚁会向前爬,速度为\(1m/s\),两只蚂蚁相遇后都会掉头,问你\(t\)秒后每只蚂蚁的位置。

  \(n\leq 100000\)

题解

  ypl大神把这个东西叫做弹性碰撞。有两个定理:

   ypl定理1:如果忽略个体之间的差异, 那么每个物体的运动可以看作是独立的。

   ypl定理2:如果不忽略个体之间的差异, 那么物体之间的相对顺序不会发生改变。

  如果这不是一个环,而是一条直线,那就很简单了。我们可以把最终位置排序,那么最终从左到右的第\(i\)只蚂蚁回到从左到右的第\(i\)个位置上。

  现在是在环上。我们要尝试找出第\(1\)只蚂蚁最终会在排序之后的哪个位置上。假设没有蚂蚁经过\(l-1\)~\(0\)这段,那么就在第一个位置上(和直线没什么区别)。每有一只蚂蚁从\(0\)逆时针走到\(l-1\),那么最终位置就会往前一位。类似的,每有一只蚂蚁总\(l-1\)顺时针走到\(0\),那么最终位置就会向后一位。

  我们可以在\(O(n)\)内统计数量,在\(O(n)\)内排序(因为输入是有序的),所以总时间复杂度是\(O(n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
int x[100010];
int w[100010];
int y[100010];
int n,l,t;
int x1[100010];
int x2[100010];
int x3[100010];
int x4[100010];
int t1=0,t2=0,t3=0,t4=0;
int main()
{
#ifdef DEBUG
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	scanf("%d%d%d",&n,&l,&t);
	int len=t%l;
	int i;
	int c=0;
	for(i=1;i<=n;i++)
	{
		scanf("%d%d",&x[i],&w[i]);
		if(w[i]==1)
		{
			c+=(t+x[i])/l;
			y[i]=(x[i]+len)%l;
			if(y[i]>=len)
				x3[++t3]=y[i];
			else
				x1[++t1]=y[i];
		}
		else
		{
			c-=(t-x[i]+l-1)/l;
			y[i]=(x[i]-len+l)%l;
			if(y[i]>=l-len)
				x4[++t4]=y[i];
			else
				x2[++t2]=y[i];
		}
		c=(c%n+n)%n;
	}
	for(i=1;i<=t3;i++)
		x1[++t1]=x3[i];
	for(i=1;i<=t4;i++)
		x2[++t2]=x4[i];
	int cnt=0,j=1;
	i=1;
	while(i<=t1||j<=t2)
	{
		if(j>t2||(i<=t1&&x1[i]<=x2[j]))
			y[++cnt]=x1[i++];
		else
			y[++cnt]=x2[j++];
	}
	for(i=c+1;i<=n;i++)
		printf("%d\n",y[i]);
	for(i=1;i<=c;i++)
		printf("%d\n",y[i]);
	return 0;
}
posted @ 2018-03-05 21:15  ywwyww  阅读(341)  评论(0编辑  收藏  举报