题解:P7804 [JOI Open 2021] 决算报告 / Financial Report
前言
提供一个不同的做法。
题解
这个东西显然考虑 dp。设
首先因为选了
但是这样是有一点问题的,因为我们的转移是矩形最值,而扫描线只能维护一个线段的信息,所以我们考虑将矩形信息压进一个线段中。于是我们用线段树维护
代码
/*
* @Author: Nekopedia
* @Date: 2025-11-22 10:48:14
* @Last Modified by: Nekopedia
* @Last Modified time: 2025-11-22 14:26:31
*/
#include <bits/stdc++.h>
#define ll long long
#define gc() (p1 == p2 and (p2 = (p1 = buf) + fread(buf, 1, S, stdin), p1 == p2) ? EOF : *p1++)
#define pc putchar
using namespace std;
const int N = 3e5 + 5, S = 1 << 22;
char buf[S], *p1, *p2;
inline ll rd(){
ll x = 0, f = 1; char c = gc();
while(! isdigit(c)){if(c == '-')f = - f; c = gc();}
while(isdigit(c)){x = (x << 3) + (x << 1) + (c ^ 48); c = gc();}
return x * f;
}
inline void wt(ll x){
if(x < 0)pc('-'), x = - x; static short st[20], top(0);
do st[++top] = x % 10, x /= 10; while(x);
while(top)pc(st[top--] ^ 48);
}
void fileio(const string &s){
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
int n, m, d, a[N], b[N];
#define ls x << 1
#define rs ls | 1
#define lson ls, l, mid
#define rson rs, mid + 1, r
int ma[N << 2], tg[N << 2];
inline void pu1(int x){ma[x] = max(ma[ls], ma[rs]);}
inline void add(int x, int y){ma[x] = tg[x] = y;}
inline void pd(int x){if(~ tg[x])add(ls, tg[x]), add(rs, tg[x]); tg[x] = - 1;}
inline void mdf1(int x, int l, int r, int ql, int qr, int y){
if(ql <= l and r <= qr)return add(x, y); int mid = l + r >> 1; pd(x);
if(ql <= mid)mdf1(lson, ql, qr, y); if(mid < qr)mdf1(rson, ql, qr, y); pu1(x);
}
inline int qry(int x, int l, int r, int ql, int qr){
if(ql <= l and r <= qr)return ma[x]; int mid = l + r >> 1; pd(x);
return max(ql <= mid ? qry(lson, ql, qr) : 0, mid < qr ? qry(rson, ql, qr) : 0);
}
int s[N << 2];
inline void pu2(int x){s[x] = s[ls] + s[rs];}
inline void mdf2(int x, int l, int r, int p, int y){
if(l == r)return s[x] += y, void(); int mid = l + r >> 1;
p <= mid ? mdf2(lson, p, y) : mdf2(rson, p, y); pu2(x);
}
inline int fd(int x, int l, int r){
if(l == r)return l; int mid = l + r >> 1;
if(! s[ls])return fd(rson); return fd(lson);
}
const string FileName = "qyuan";
signed main(){
fileio(FileName);
n = rd(), d = rd();
for(int i = 1; i <= n; ++i)a[i] = b[i] = rd();
sort(a + 1, a + 1 + n); m = unique(a + 1, a + 1 + n) - a - 1;
for(int i = 1; i <= n; ++i)b[i] = lower_bound(a + 1, a + 1 + m, b[i]) - a;
for(int i = 1; i <= m << 2; ++i)tg[i] = - 1;
for(int i = 1; i <= n; ++i){
if(i - d > 1)mdf2(1, 1, m, b[i - d - 1], - 1);
int r = fd(1, 1, m); if(i - d > 1 and b[i - d - 1] < r)
mdf1(1, 1, m, b[i - d - 1], r - 1, 0);
mdf2(1, 1, m, b[i], 1);
if(b[i] > 1){
int x = max(qry(1, 1, m, 1, b[i] - 1) + 1, qry(1, 1, m, b[i], b[i]));
mdf1(1, 1, m, b[i], b[i], x);
}
else mdf1(1, 1, m, 1, 1, 1);
}
return wt(qry(1, 1, m, b[n], m)), 0;
}
// 于是纵横万相穷通 也守心底灵通
// 合眼识得星沉地动 也岿然不动
// 敢令岁月乌有 逍遥长驻 敢归云间宿
// 遥祝远行人 有道不孤