版权声明:欢迎大家转载,转载请标明出处。 https://blog.csdn.net/ylsoi/article/details/83115841
题目大意:
给定一个序列,每一次将 位置的值修改为 (不对后面产生影响),求修改后的LIS。
思路:
首先每一次修改后变化的数值一定不会很大,变化的绝对值
。
考虑什么时候答案减小,不难发现只有这个元素为LIS的关键元素才有可能减小。
考虑什么时候答案增大,即这个元素不是关键元素,从可能而插入原有的LIS中。
于是我们便有了一个做法:
如果这个元素为原序列LIS的关键元素,那么考虑继续将这个元素加入LIS中时答案是否还是原来的答案,否则为ans-1。
如果这个元素不为原序列LIS的关键元素,那么答案一定不会减小,于是我们将这个元素加入LIS中看答案是否增加。
考虑如何将每一个修改都尝试加入LIS中,当然可以用主席树来维护前缀的单调栈和后缀的单调栈,简单一点将询问离线并且挂在相应的位置上,正反各做一遍DP即可。
如何求一个元素是否为关键元素?看这个元素是否能成为LIS中的元素,并且看这个元素的排名是否只出现了一次。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<<x<<endl
#define pii pair<int,int>
#define fi first
#define se second
#define mk make_pair
#define pb push_back
typedef long long ll;
using namespace std;
void File(){
freopen("kite.in","r",stdin);
freopen("kite.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=5e5+10;
int n,m,h[maxn],ans,is[maxn],pos[maxn];
vector<pii>qu[maxn];
pii dp[maxn],val[maxn];
void init(){
read(n); read(m);
REP(i,1,n)read(h[i]);
int a,b;
REP(i,1,m){
read(a),read(b);
pos[i]=a;
qu[a].pb(mk(i,b));
}
}
int s[maxn],t;
void work(){
int p;
REP(i,1,n){
REP(j,0,qu[i].size()-1){
int w=qu[i][j].se,id=qu[i][j].fi;
if(!t || s[t]<w)val[id].fi=t+1;
else{
p=lower_bound(s+1,s+t+1,w)-s;
val[id].fi=p;
}
}
if(!t || s[t]<h[i])s[++t]=h[i],dp[i].fi=t;
else{
p=lower_bound(s+1,s+t+1,h[i])-s;
s[p]=h[i]; dp[i].fi=p;
}
}
ans=t;
t=n+1;
DREP(i,n,1){
REP(j,0,qu[i].size()-1){
int w=qu[i][j].se,id=qu[i][j].fi;
if(t==n+1 || s[t]>w)val[id].se=n-t+2;
else{
p=upper_bound(s+t,s+n+1,w)-s-1;
val[id].se=n-p+1;
}
}
if(t==n+1 || s[t]>h[i])s[--t]=h[i],dp[i].se=n-t+1;
else{
p=upper_bound(s+t,s+n+1,h[i])-s-1;
s[p]=h[i]; dp[i].se=n-p+1;
}
}
REP(i,1,n)if(dp[i].fi+dp[i].se-1==ans)
++is[dp[i].fi];
REP(i,1,m){
if(dp[pos[i]].fi+dp[pos[i]].se-1==ans && is[dp[pos[i]].fi]==1)
printf("%d\n",max(ans-1,val[i].fi+val[i].se-1));
else printf("%d\n",max(ans,val[i].fi+val[i].se-1));
}
}
int main(){
File();
init();
work();
return 0;
}