题意:
有 n n n节火车车厢,从左到右依次是头至尾,每个车厢有一个最高速度 v i v_{i} vi,如果后面的车的速度不小于前车 v i + 1 ≥ v i v_{i+1}\geq v_{i} vi+1≥vi,那么后车的速度会受到限制,会变为前车速度 v i v_{i} vi,反之则不受影响。我们把连续的极长一段的共速车厢看作一辆完整火车。给出 m m m个操作,每个操作给出两个整数 x d x x\ dx x dx,代表 x x x车厢的最高速度减少 d x dx dx,在每次操作后给出能组成的火车数。
方法:
利用 m a p map map或 v e c t o r vector vector,每次只保存火车头,在操作的时候,我们检查一下 x x x是否在 m a p map map里,如果在 m a p map map里有 x x x,那么这节火车头降速,然后检查后面的火车头速度是否不小于这个新的 v x v_{x} vx,如果后面的火车头的速度 ≥ v x \geq v_{x} ≥vx,那么这个火车头会被 x x x同化,直接并入 x x x所在的火车,删去这个火车头即可;如果 m a p map map里没有 x x x,那么我们需要检查一下他是否脱离了前面火车头的控制,如果脱离了控制,就说明组成了一节新的火车,然后再检查后面的是否速度是否 ≥ \geq ≥这个新的火车头的速度,如果是,那么被这个新的同化,把后面的删去即可。每次操作后输出 m a p . s i z e ( ) 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;
}