P5978 [CEOI2018] Global warming 题解
P5978 [CEOI2018] Global warming 题解
题意分析
给定长度为 \(n\) 的数组 \(\{ a_i \}\) 和一个值 \(x\),可以将某一段连续区间加上一个值 \(d \in[-x,x]\),求最大严格上升子序列长度。
思路分析
一个显然的贪心:要么把 \(a_i,\forall i \in [1,r]\) 全部减去 \(x\),要么把 \(a_i,\forall i \in [l,n]\) 全部加上 \(x\),再求最大严格上升子序列长度,因为这样肯定保证不劣于从中间加或减。
那么只需要正向来一次直接的不带修改的 DP,再从反向来一次带修改的 DP(加 \(x\)),把两次答案加一下再减一求最大值即可。
CODE
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define tomax(a,b) ((a)=max((a),(b)))
#define tomin(a,b) ((a)=min((a),(b)))
#define RCL(a,b,c,d) memset((a),(b),sizeof(c)*(d))
#define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
#define DOR(i,a,b) for(register int i=(a);i>=(b);--i)
#define EDGE(g,i,u,x) for(register int (i)=(g).h[(u)],(x)=(g).v[(i)];(i);(i)=(g).nxt[(i)],(x)=(g).v[(i)])
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0);return Main();}signed Main
using namespace std;
template<class T1,class T2>auto max(T1 a,T2 b){
return a>b?a:b;
}
constexpr int N=2e5+10;
int n,X,ans;
int a[N],f[N],h[N];
signed main(){
cin>>n>>X;
FOR(i,1,n)cin>>a[i];
RCL(h+1,INF,int,n);
FOR(i,1,n)h[f[i]=lower_bound(h+1,h+n+1,a[i])-h]=a[i],tomax(ans,f[i]);
RCL(h+1,INF,int,n);
DOR(i,n,1)tomax(ans,f[i]+(lower_bound(h+1,h+n+1,-a[i]+X)-h-1)),h[lower_bound(h+1,h+n+1,-a[i])-h]=-a[i];
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号