题意
有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()
- {
-
-
- int t,C = 1;
-
- 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;
- }