考察set的灵活使用。本题要求输出原序列严格递减子序列的长度,set存每一段相同的子串的头下标。在询问时,首先明白每次操作最多能使答案+1,产生的原因是a[k]-d使得原本大于之前的a[k]现在小于前面那一段了,因此k可以插入到set里面。同时a[k] - d也使得当前的a[k]可能会把之后原本小于a[k]的现在大于a[k] - d了,a[k]会抹平这些元素,因此遍历删除即可。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <math.h>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define endl '\n'
const int maxn = 1e5 + 5;
int a[maxn],n,q;
void solve(){
cin >> n >> q;
set<int> s;
int last = 1;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
if (s.empty() || a[i] < a[last]){
last = i;
s.insert(i);
}
}
while (q --){
int k,d;
cin >> k >> d;
a[k] -= d;
auto p = s.upper_bound(k);
if (p != s.begin()){
p = prev(p);
if (a[*p] > a[k]) s.insert(k);
}
p = s.upper_bound(k);
while (true){
if (p == s.end()) break;
if (a[k] <= a[*p]){
p = s.erase(p);
} else break;
}
cout << s.size() << ' ';
}
cout << endl;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T = 1;
cin >> T;
while (T--) solve();
}
下面再提供一下此题的线段树做法
线段树进行区间合并即可,需要考虑许多细节,请参考《楼房重建》
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <math.h>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define endl '\n'
#define lson node << 1
#define rson node << 1 | 1
const int maxn = 1e5 + 5;
struct node{
int val;
double maxx;
}t[maxn << 2];
double a[maxn];
int n,q;
void pushup1(int node){
t[node].maxx = min(t[lson].maxx,t[rson].maxx);
}
int pushup2(int node,double lx,int l,int r){
int mid = l + r >> 1;
if (l == r) return a[l] < lx;
if (t[node].maxx >= lx) return 0;
if (a[l] < lx) return t[node].val;
if (t[lson].maxx >= lx) return pushup2(rson,lx,mid + 1,r);
return pushup2(lson,lx,l,mid) + t[node].val - t[lson].val;
}
void build(int l,int r,int node){
if (l == r){
t[node].maxx = a[l];
t[node].val = 1;
return;
}
int mid = l + r >> 1;
build(l,mid,lson);
build(mid + 1,r,rson);
pushup1(node);
t[node].val = t[lson].val + pushup2(rson,t[lson].maxx,mid + 1,r);
}
void update(int l,int r,int node,int x,double k){
if (l == r){
t[node].maxx = k;
t[node].val = 1;
return;
}
int mid = l + r >> 1;
if (x <= mid) update(l,mid,lson,x,k);
else update(mid + 1,r,rson,x,k);
pushup1(node);
t[node].val = t[lson].val + pushup2(rson,t[lson].maxx,mid + 1,r);
}
void solve(){
cin >> n >> q;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
build(1,n,1);
while (q --){
int x,y;
cin >> x >> y;
a[x] -= y;
update(1,n,1,x,a[x]);
cout << t[1].val << ' ';
}
cout << endl;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T = 1;
cin >> T;
while (T--) solve();
}