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]变化后三种情况:
  1. 比前面的数大,a[pos]不维护
  2. 比前面的数小,比后面的数大,往后删除比a[pos]小的
  3. 比前面的数小,比后面的数小,只差入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;
}
posted @ 2022-07-11 22:02  qingyanng  阅读(29)  评论(0编辑  收藏  举报