题解:CF1690G Count the Trains
思路: 首先我们可以理清一下各种情况:
1)m可能为0
2)一次操作时,只需要考虑每节火车的车头。
3)当一节火车的速度降低时,只会影响它及它后面的车厢
当m=0时,我们可以记录上一节车头的速度从而O(n) 解决问题
同理,一节车厢会不会成为车头取决于上一节车头的速度,也就是前面车厢的状态不会改变。 当车厢 k 操作时,首先向后遍历车头 x;
- 如果 ax≥ak-d,那么x 将不再是车头。
然后比较新车厢和这节车厢前的第一个车头y
- 若ay≥ak-d,那么ak就是新的车头
我们可以发现能用set做,时间复杂度为O(nlogn)
代码:
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int t,a[N]; int main(){scanf("%d",&t);while(t--){int n,m;scanf("%d%d",&n,&m);set<int> s;for(int i = 1;i <= n;i ++){scanf("%d",&a[i]);if(!s.size()||a[i]<a[*(--s.end())]){s.insert(i);}} while(m--){int k,d;scanf("%d%d",&k,&d);int x=a[k]-d;while(s.lower_bound(k)!=s.end()&&a[*s.lower_bound(k)]>=x) {s.erase(*s.lower_bound(k));}if(s.lower_bound(k)==s.begin()||a[*(--s.lower_bound(k))]>x){s.insert(k);}a[k]-=d;printf("%d ",s.size());}printf("\n");} }