有\(n\)只青蛙在一个长度为\(m\)的环上打架;每只青蛙有一个初始位置\(p_i\),和一个跳跃数值\(a_i\)。从\(1\)号青蛙开始按序号循环行动,每次若第\(i\)只青蛙行动,则它会向前跳 \(a_i\)个格子,撞飞它遇见的所有青蛙,包括终点格子上的,之后它的\(a_i\)减少等同于撞飞的青蛙只数,若\(a_i<0\),它不会移动。求最后剩下的所有青蛙的编号。\(n\leq 10^5,m\leq 10^9\),\(p\)互不不同


这类问题就往相对位置的方向想吧,,,

在第一次有青蛙撞飞其他青蛙之前,他们的相对位置都是不变的。所以考虑优化最朴素的模拟,即维护出第一次撞飞别人是什么时候以及哪只青蛙撞。所以一个优化的算法就是撞飞一只青蛙之后重新计算所有青蛙的位置。又由于每个青蛙只需要注意它正前方的那只,所以我们可以做一个链表来维护青蛙的相对位置。这样复杂度还是很高。但可以发现撞飞别人以后仍然有很多青蛙的相对位置没有变。如果我们每次都通过\(初始距离之差/a之差\)来计算青蛙相撞的时间,当某只青蛙撞完别人并且a减1之后,我们仍然用这个公式算就会有误差。假设这只青蛙在\(t\)时刻撞了别人,可以发现我们让它的位置往前挪\(t\)个单位就可以消除这个误差。所以我们就有一个新的算法,即每次相撞后修改一下撞击者的位置。这样就是\(O(nlogn)\)了。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define cn const
#define gc getchar()
#define fp(i,a,b) for(rg int i=(a),ed=(b);i<=ed;++i)
#define fb(i,a,b) for(rg int i=(a),ed=(b);i>=ed;--i)
#define mp make_pair
using namespace std;
typedef cn int cint;
typedef pair<int,int> pr;
il int rd(){
rg int x(0),f(1); rg char c(gc);
while(c<'0'||'9'<c){if(c=='-')f=-1;c=gc;}
while('0'<=c&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=gc;
return x*f;
}
cint maxn=1e5+10,inf=0x3f3f3f3f;
int n,m,pre[maxn],nxt[maxn];
set<pr> st;
struct frog{int p,a,id;}a[maxn];
il bool cmp(cn frog &a,cn frog &b){return a.p<b.p;}
il bool cmp2(cn frog &a,cn frog &b){return a.id<b.id;}
il int calc(int x,int y){
frog p=a[x],q=a[y];
rg int res=0;
if(x<y){
rg int tmp=p.p,now=tmp+p.a,now2=q.p;
p.p=(p.p+p.a-1)%m+1,res=1;
if(now2<tmp)now2+=m;
if(tmp<=now2&&now2<=now)return 1;
}
rg int dis=(q.p-p.p+m)%m,dec=p.a-q.a;
if(dec<=0)return inf;
return res+(dis+dec-1)/dec;
}
int main(){
n=rd(),m=rd();
fp(i,1,n)a[i].p=rd(),a[i].a=rd(),a[i].id=i;
sort(a+1,a+1+n,cmp);
pre[a[1].id]=a[n].id,nxt[a[1].id]=a[2].id,nxt[a[n].id]=a[1].id,pre[a[n].id]=a[n-1].id;
fp(i,2,n-1)pre[a[i].id]=a[i-1].id,nxt[a[i].id]=a[i+1].id;
sort(a+1,a+1+n,cmp2);
fp(i,1,n)st.insert(mp(calc(i,nxt[i]),i));
int fl=0;
while(st.size()){
set<pr>::iterator it=st.begin();
if(it->first==inf)break;
rg int i=it->second,tem=it->first;
st.erase(it);
st.erase(mp(calc(nxt[i],nxt[nxt[i]]),nxt[i]));
st.erase(mp(calc(pre[i],i),pre[i]));
--a[i].a,a[i].p=(a[i].p+tem-1)%m+1;
pre[nxt[nxt[i]]]=i,nxt[i]=nxt[nxt[i]];
st.insert(mp(calc(pre[i],i),pre[i]));
st.insert(mp(calc(i,nxt[i]),i));
}
printf("%d\n",st.size());
for(auto &x:st)printf("%d ",x.second);
return 0;
}

CF625E Frog Fights的更多相关文章

  1. 【CF625E】Frog Fights(模拟)

    [CF625E]Frog Fights(模拟) 题面 CF 洛谷 翻译: 有\(n\)只青蛙在一个被分为了\(m\)等分的圆上,对于每份顺时针依次标号. 初始时每只青蛙所在的位置是\(p_i\),速度 ...

  2. Codeforces Round #342 (Div. 2) E. Frog Fights set 模拟

    E. Frog Fights 题目连接: http://www.codeforces.com/contest/625/problem/E Description stap Bender recentl ...

  3. Codeforces Round #342 (Div 2) 解题报告

    除夕夜之有生之年CF第一场 下午从奶奶家回到姥姥家,一看还有些时间,先吃点水果陪姥姥姥爷聊了会儿,再一看表,5:20....woc已经开场20分钟了...于是抓紧时间乱搞.. **A. Guest F ...

  4. [LeetCode] Frog Jump 青蛙过河

    A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...

  5. hdu5037 Frog (贪心)

    http://acm.hdu.edu.cn/showproblem.php?pid=5037 网络赛 北京 比较难的题 Frog Time Limit: 3000/1500 MS (Java/Othe ...

  6. CF #305 (Div. 2) C. Mike and Frog(扩展欧几里得&&当然暴力is also no problem)

    C. Mike and Frog time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  7. Frog Jump

    A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...

  8. POJ 1054 The Troublesome Frog

    The Troublesome Frog Time Limit: 5000MS Memory Limit: 100000K Total Submissions: 9581 Accepted: 2883 ...

  9. Leetcode: Frog Jump

    A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...

随机推荐

  1. 2020-2021-1 20209307《Linux内核原理与分析》第五周作业

    一.理论知识 系统调用:操作系统为用户态进程与硬件设备进行交互提供的一组接口. 系统调用的三层皮:API(应用程序接口),中断向量system_call,中断服务程序sys_xyz 宏观上Linux操 ...

  2. 处理fMRI数据的一些常用Matlab命令

    背景 处理fMRI数据常常用到MATLAB,在此记录一些常用代码及功能. 1.读取原始DICOM数据 1-1 读入dicom图像并绘图: Image = dicomread('fMRI.dcm'); ...

  3. kali 2020安装docker

    环境准备 kali虚拟机2020.01x64位版本 安装docker官方文档:https://docs.docker.com/engine/installation/linux/docker-ce/d ...

  4. Linux课程知识点总结(一)

    Linux课程知识点总结(一) 一.Linux系统的简介 1.1 什么是Linux Linux是一个免费的多用户.多任务的操作系统,其运行方式.功能和Unix系统很相似,但Linux系统的稳定性.安全 ...

  5. Python手把手教程之用户输入input函数

    函数input() 函数 input() 让程序暂停运行,等待用户输入一些文本.获取用户输入后,Python将其存储在一个变量中,以方便你使用. 例如,下面的程序让用户输入一些文本,再将这些文本呈现给 ...

  6. Entity Framework 更新失败,调试后发现是AsNoTracking的原因

    public override int SaveChanges() { var changedEntities = ChangeTracker.Entries().Where(e => e.St ...

  7. C#获取时间戳的几种方式

    Console.WriteLine(Convert.ToDouble(DateTime.UtcNow.Ticks - 621355968000000000) / (10 * 1000 * 1000)) ...

  8. 常见的JS手写函数汇总(代码注释、持续更新)

    最近在复习面试中常见的JS手写函数,顺便进行代码注释和总结,方便自己回顾也加深记,内容也会陆陆续续进行补充和改善. 一.手写深拷贝 <script> const obj1 = { name ...

  9. kaggle入门题Titanic

    集成开发环境:Pycharm python版本:2.7(anaconda库) 用到的库:科学计算库numpy,数据分析包pandas,画图包matplotlib,机器学习库sklearn 大体步骤分为 ...

  10. 如何定位CPU瓶颈?

    CPU是通常大家最先关注的性能指标,宏观维度有核的CPU使用率,微观有函数的CPU cycle数,根据性能的模型,性能规格与CPU使用率是互相关联的,规格越高,CPU使用率越高,但是处理器的性能往往又 ...