【题解】[JOI Open 2021] Financial Report

首先考虑 \(D = n\) 的情况,有方程 \(f_i = \max\limits_{j < i\land a_j<a_i}\{f_j + 1\}\)​。

对于 \(D\) 的限制,我们对每个位置计算 \(p_i\) 表示从 \(i\) 开始,每次最多向前跳 \(D\) 格,只能跳到 \(\le a_i\) 的格子上,能够到达的最小格子。显然这可以直接用 set + 并查集维护。

那么我们方程修改为 \(f_i = \max\limits_{p_i\le j < i\land a_j<a_i}\{f_j + 1\}\)​。直接用线段树优化 DP 即可,时间复杂度 \(\mathcal{O}(N\log N)\)。

/*
    Author : SharpnessV
    Right Output ! & Accepted !
*/
#include<bits/stdc++.h>
//#define int long long

#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define pre(i, a, b) for(int i = (a);i >= (b);i--)
#define rp(i, a) for(int i = 1; i <= (a); i++)
#define pr(i, a) for(int i = (a); i >= 1; i--)
#define go(i, x) for(auto i : x)

#define mp make_pair
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define ze(p) memset(p, 0, sizeof(p))
#define mem(p, x) memset(p, x, sizeof(p))
#define YES puts("YES")
#define NO puts("NO")
#define Yes puts("Yes")
#define No puts("No")
#define si(x) (int)(x).size()
#define db cerr
#define pc putchar
#define gc getchar
#define el putchar('\n')

using namespace std;
const double eps = 1e-15, pi = 3.1415926535897932385;
typedef long long LL;
typedef pair<int,int> Pr;
const int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1}, inf = 0x7fffffff;
//Author : SharpnessV
//#define main Solution
//char buf[1<<22],*p1=buf,*p2=buf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read(){
    int x = 0;bool f = 1;char ch = gc();
    while(!isdigit(ch))f = ('-' == ch ? 0 : 1), ch = gc();
    while(isdigit(ch))x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
    if(f)return x;return -x;
}
inline LL Read(){
    LL x = 0;bool f = 1;char ch = gc();
    while(!isdigit(ch))f = ('-' == ch ? 0 : 1), ch = gc();
    while(isdigit(ch))x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
    if(f)return x;return -x;
}
int gcd(int x,int y){return y ? gcd(y, x % y) : x;}
int lcm(int x,int y){return x / gcd(x, y) * y;}
#define P 1000000007
//#define P 998244353
#define bas 229
inline void ad(int &x, int y){x += y; if(x >= P) x -= P;}
inline void su(int &x, int y){x -= y; if(x < 0) x += P;}
inline void cmn(int &x,int y){if(y < x) x = y;}
inline void cmx(int &x,int y){if(y > x) x = y;}
inline void cmn(LL &x, LL y){if(y < x) x = y;}
inline void cmx(LL &x, LL y){if(y > x) x = y;}

int Pow(int x, int y){
	if(y < 0)return Pow(Pow(x, P - 2), -y);
	int now = 1 ;
	for(;y;y >>= 1, x = 1LL * x * x % P)if(y & 1) now = 1LL * now * x % P;
	return now;
}

/*******************************************************************************************************************/
/*                                                                                                                 */
/*******************************************************************************************************************/

#define N 300005

int n, m, u[N], fa[N], f[N], b[N], T;
int get(int x){return fa[x] == x ? x : fa[x] = get(fa[x]);}
set<int>s;vector<int>c[N];

struct node{
	int l, r, val;
}a[N << 2];
#define L a[x].l
#define R a[x].r
#define ls (x << 1)
#define rs (ls | 1)
#define S a[x].val

void build(int x,int l,int r){
	L = l, R = r, S = 0xcfcfcfcf;
	if(l == r)return;
	int mid = (l + r) >> 1;
	build(ls, l, mid), build(rs, mid + 1, r);
}

void ins(int x,int pos,int val){
	if(L == R)S = val;
	else{
		int mid = (L + R) >> 1;
		if(mid >= pos)ins(ls, pos, val);
		else ins(rs, pos, val);
		S = max(a[ls].val, a[rs].val);
	}
}

int ask(int x,int l,int r){
	if(L >= l && R <= r)return S;
	int mid = (L + R) >> 1, cur = 0xcfcfcfcf;
	if(mid >= l)cmx(cur, ask(ls, l, r));
	if(mid < r)cmx(cur, ask(rs, l, r));
	return cur;
}

int main(){
	//int T = read();while(T--)solve();
	n = read(), m = read();
	rp(i, n)b[i] = u[i] = read(), fa[i] = i;
	sort(b + 1, b + n + 1), T = unique(b + 1, b + n + 1) - b - 1;
	rp(i, n)u[i] = lower_bound(b + 1, b + T + 1, u[i]) - b, c[u[i]].pb(i);
	rp(i, T){
		go(x, c[i]){
			auto k = s.lower_bound(x);
			if(k != s.end() && x + m >= *k && fa[*k] > x)fa[*k] = x;
			if(k != s.begin()){
				k--;if(*k + m >= x)fa[x] = *k;
			}s.insert(x);
		}
		go(x, c[i])f[x] = get(x);
	}
	build(1, 1, n);
	rp(i, T){
		go(x, c[i])u[x] = max(1, ask(1, f[x], x) + 1);
		go(x, c[i])ins(1, x, u[x]);
	}
	printf("%d\n",a[1].val);
	return 0;
}
上一篇:浅谈 线性渐变(linear-gradient)


下一篇:学习记录