题意:
给出一个序列,询问会修改序列中的一个数字,然后问从1—n,最大值变化的次数。每次询问之间是独立的。
思路:
首先计算出每个位置开始到最后的最大值变化次数,每个位置的上一个最大值的位置。
通过rmq+二分可以计算出当前位置在当前询问值的情况下,下一个最大值更新的位置在哪里,然后通过预处理的信息前后合并即可。
代码:
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <string>
#include <bitset>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#define X first
#define Y second
#define pb push_back
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define sd(n) scanf("%d",&n)
#define sf(n) scanf("%lf",&n)
#define cout1(x) cout<<x<<endl
#define ALL(x) x.begin(),x.end()
#define sdd(n,m) scanf("%d%d",&n,&m)
#define INS(x) inserter(x,x.begin())
#define mst(a,b) memset(a,b,sizeof(a))
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define cout2(x,y) cout<<x<<" "<<y<<endl
#define qclear(a) while(!a.empty())a.pop()
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define IOS std::ios::sync_with_stdio(false)
#define SRAND srand((unsigned int)(time(0)))
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define cout3(x,y,z) cout<<x<<" "<<y<<" "<<z<<endl
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
using namespace std;
const double PI=acos(-1.0);
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const ll mod=998244353;
const int maxn=200005;
const int maxm=300005;
int n,m;
int a[maxn];
int d[maxn][32];
void rmqinit(int* a,int len) {
mst(d,0);
for(int i=1; i<=len; i++)
d[i][0]=a[i];
for(int j=1; (1<<j)<=len+1; j++) {
for(int i=1; i+(1<<j)-1<=len; i++) {
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
}
}
int rmq(int l,int r) {
int k=0;
while((1<<(k+1))<=r-l+1)
k++;
return max(d[l][k],d[r-(1<<k)+1][k]);
}
int getpos(int pos,int val) {
int l,r,ans;
l=pos+1;
r=n+1;
ans=r;
while(l<=r) {
int mid=(l+r)>>1;
if(rmq(pos+1,mid)>val) {
ans=mid;
r=mid-1;
} else {
l=mid+1;
}
}
return ans;
}
int dp[maxn];
bool sel[maxn];
int pre[maxn];
int precnt[maxn];
int allcnt;
void init() {
dp[n+1]=0;
for(int i=n; i>=1; i--) {
int pos=getpos(i,a[i]);
dp[i]=dp[pos]+1;
}
sel[1]=1;
pre[1]=-1;
precnt[1]=1;
int lst=1;
int lstval=a[1];
int cnt=1;
for(int i=2; i<=n; i++) {
sel[i]=0;
pre[i]=lst;
precnt[i]=cnt;
if(a[i]>lstval) {
lst=i;
lstval=a[i];
sel[i]=1;
precnt[i]=++cnt;
}
}
allcnt=cnt;
}
void solve() {
int t;
sd(t);
while(t--) {
sdd(n,m);
for(int i=1; i<=n; i++)
sd(a[i]);
rmqinit(a,n);
init();
for(int i=0; i<m; i++) {
int pos,val;
sdd(pos,val);
int ans=0;
if(sel[pos]) {
if(pos==0) {
ans=1+dp[getpos(pos,val)];
} else {
if(val>a[pre[pos]]) {
ans=precnt[pos]+dp[getpos(pos,val)];
} else {
ans=precnt[pre[pos]]+dp[getpos(pos,a[pre[pos]])];
}
}
} else {
if(val>a[pre[pos]]) {
ans=precnt[pre[pos]]+1+dp[getpos(pos,val)];
} else {
ans=allcnt;
}
}
printf("%d\n",ans);
}
}
return ;
}
int main() {
#ifdef LOCAL
freopen("j.in","r",stdin);
freopen("out.txt","w",stdout);
#else
// freopen("","r",stdin);
// freopen("","w",stdout);
#endif
solve();
return 0;
}