[CF650D]Zip-line——动态LIS dalaos' blogs Some Links

版权声明:欢迎大家转载,转载请标明出处。 https://blog.csdn.net/ylsoi/article/details/83115841

题目大意:

给定一个序列,每一次将 a i a_i 位置的值修改为 b i b_i (不对后面产生影响),求修改后的LIS。

思路:

首先每一次修改后变化的数值一定不会很大,变化的绝对值 1 \leq 1
考虑什么时候答案减小,不难发现只有这个元素为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;
}

猜你喜欢

转载自blog.csdn.net/ylsoi/article/details/83115841
今日推荐