题意
有n只青蛙,站在m大的一个环形上面
青蛙的位置是pi,每次移动ai
每只青蛙按照编号顺序移动,会撞掉他所经过的青蛙,每撞掉一只,会使得这只青蛙移动的距离减小1
然后问你一直循环下去,还剩下哪些青蛙
题解:
模拟
但是别按照编号的顺序去模拟,我们按照相撞的时间先后顺序去模拟就好了
首先我们可以得到一个信息,这只青蛙如果会和别的青蛙相撞,那么最先相撞的,肯定是他的下一只青蛙。
然后我们把相撞的时间记录下来(究竟是第几个回合,才会撞到那只青蛙
然后我们用一个Set或者优先队列,不断模拟这个过程就好了
每次抽出相撞时间最短的青蛙来,然后撞掉。
最后剩下的青蛙都不相撞为止。
因为每次更新的复杂度是logn,每次更新必定会减小一只青蛙,所以复杂度是nlogn的
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 1000100
#define MOD 1000000007
#include<bits/stdc++.h>
int n,m;
int p[maxn],a[maxn];
int nxt[maxn],pre[maxn];
set<pair<int,int> > S;
pair<int,int> c[maxn];
int time(int x,int y)
{
if(x == y)
return INF;
long long p1 = p[x],p2 = p[y];
if(x > y)
p2 = (p2 + a[y]) % m;
if(p2 < p1)
p2 += m;
if(p2 - p1 <= a[x])
return 1;
if(a[y] >= a[x])
return INF;
int l = 1,r = INF,ans = INF;
while(l <= r)
{
int mid = (l + r) >> 1;
if(p1 + 1ll*a[x]*mid >= p2 + 1ll*a[y]*(mid-1))
ans = mid,r = mid - 1;
else
l = mid + 1;
}
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t,C = 1;
//scanf("%d",&t);
while(scanf("%d%d",&n,&m) != EOF)
{
for(int i = 0; i < n; i++)
{
scanf("%d%d",&p[i],&a[i]);
p[i]--;
c[i].first = p[i];
c[i].second = i;
}
sort(c,c+n);
for(int i = 0; i < n; i++)
{
nxt[c[i].second] = c[(i+1)%n].second;
pre[c[i].second] = c[(i-1+n)%n].second;
}
for(int i = 0; i < n; i++)
S.insert(make_pair(time(i,nxt[i]),i));
while(!S.empty())
{
pair<int,int> now = *S.begin();
if(now.first == INF)
break;
S.erase(now);
int x = now.second;
S.erase(make_pair(time(nxt[x],nxt[nxt[x]]),nxt[x]));
S.erase(make_pair(time(pre[x],x),pre[x]));
p[x] += now.first,a[x]--;
nxt[x] = nxt[nxt[x]];
pre[nxt[x]] = x;
S.insert(make_pair(time(pre[x],x),pre[x]));
S.insert(make_pair(time(x,nxt[x]),x));
}
printf("%d\n",S.size());
for(set<pair<int,int> >::iterator it = S.begin(); it != S.end(); it++)
printf("%d ",(*it).second+1);
printf("\n");
}
return 0;
}