Codeforces 1690G 思维

该篇博客介绍了一个关于火车车厢速度限制的问题,每个车厢有自己的最高速度,当后面车厢速度不低于前面车厢时,其速度会被限制。博主提出了一种解决方案,利用map或vector存储火车头信息,在每次车厢速度减少的操作后更新火车头状态,并计算出当前可组成的火车数量。通过一系列操作后,输出每次操作后的火车数,以此解决这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

nnn节火车车厢,从左到右依次是头至尾,每个车厢有一个最高速度viv_{i}vi,如果后面的车的速度不小于前车vi+1≥viv_{i+1}\geq v_{i}vi+1vi,那么后车的速度会受到限制,会变为前车速度viv_{i}vi,反之则不受影响。我们把连续的极长一段的共速车厢看作一辆完整火车。给出mmm个操作,每个操作给出两个整数x dxx\ dxx dx,代表xxx车厢的最高速度减少dxdxdx,在每次操作后给出能组成的火车数。

方法:

利用mapmapmapvectorvectorvector,每次只保存火车头,在操作的时候,我们检查一下xxx是否在mapmapmap里,如果在mapmapmap里有xxx,那么这节火车头降速,然后检查后面的火车头速度是否不小于这个新的vxv_{x}vx,如果后面的火车头的速度≥vx\geq v_{x}vx,那么这个火车头会被xxx同化,直接并入xxx所在的火车,删去这个火车头即可;如果mapmapmap里没有xxx,那么我们需要检查一下他是否脱离了前面火车头的控制,如果脱离了控制,就说明组成了一节新的火车,然后再检查后面的是否速度是否≥\geq这个新的火车头的速度,如果是,那么被这个新的同化,把后面的删去即可。每次操作后输出map.size()map.size()map.size()即可

#include<bits/stdc++.h>
#define ll long long
#define fr first
#define se second
using namespace std;

int read()
{
	int ret=0,base=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') base=-1;
		ch=getchar();
	}
	while(isdigit(ch))
	{
		ret=(ret<<3)+(ret<<1)+ch-48;
		ch=getchar();
	}
	return ret*base;
}

int n,m,a[100005];
vector<int>ans;
map<int,int>map1;

void work()
{
	map1.clear();
	ans.clear();
	n=read();m=read();
	for(int i=1;i<=n;i++) a[i]=read();
	int l=1,r=1;
	while(l<=n)
	{
		while(r+1<=n&&a[r+1]>=a[l]) r++;
		map1[l]=a[l];
		l=++r;
	}
	while(m--)
	{
		int x=read(),dx=read();
		a[x]-=dx;
		if(map1.count(x))
		{
			map1[x]-=dx;
			auto it=map1.lower_bound(x); it++;
			while(it!=map1.end()&&it->se>=map1[x]){
				map1.erase(it--);it++;
			}
		}
		else
		{
			auto it=map1.lower_bound(x); it--;
			//it不可能是begin(),因为第一节车厢一定是一个火车头
			if(it->se>a[x]) 
			{
				map1[x]=a[x];
				it=map1.lower_bound(x); it++;
				while(it!=map1.end()&&it->se>=map1[x]){
					map1.erase(it--);it++;
				}
			}
		}
		ans.push_back(map1.size());
	}
	for(auto i:ans) printf("%d ",i);
	putchar('\n');
}

int main()
{
	int t=read();
	while(t--) work();
 	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值