CF1690G (STL乱搞)
https://codeforces.com/problemset/problem/1690/G
- pos减少之后,如果a[pos] 小于 a[pos - 1],那么车厢组数会减少 sum[r] - sum[pos]个,r是pos后面第一个小于a[pos]的位置,sum是前缀最长递减子序列长度
- 所以要考虑如何快速找到r,计算sum
- 考虑暴力优化: pos肯定不能直接往后枚举,只有递减子序列是有贡献的,如果只维护递减子序列,a[pos]变化后三种情况:
- 比前面的数大,a[pos]不维护
- 比前面的数小,比后面的数大,往后删除比a[pos]小的
- 比前面的数小,比后面的数小,只差入a[pos]
第2种操作: 所有询问的时间复杂度均摊是On的
- map:<pos, val> 实现操作
尝试暴力优化
#include<bits/stdc++.h>
//#include <bits/extc++.h>
using namespace std;
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define ull unsigned long long
#define li __int128_t
#define PII pair<int, int>
#define re register
//#define int long long
const int N = 2e5 + 5;
const int M = 1e6 + 5;
const int mod = 1e9 + 7;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
int a[N]; map<int, int> mp;
void add ( int i, int x ) {
mp[i] = x;
auto it = mp.find(i);
if( it != mp.begin() && prev(it) -> second <= x ) { mp.erase(it); return; }
while( next(it) != mp.end() && next(it) -> second >= x ) mp.erase(next(it));
}
void solve() {
mp.clear();
int n, m ; cin >> n >> m;
for ( int i = 1; i <= n; ++ i ) cin >> a[i];
for ( int i = 1; i <= n; ++ i ) add( i, a[i] );
while( m -- ) {
int pos, val; cin >> pos >> val;
add( pos, a[pos] -= val);
cout << mp.size() << " \n"[m == 0];
}
}
int main() {
IOS
int t; cin >> t;
while( t --) solve();
return 0;
}