제출 #422543

#제출 시각아이디문제언어결과실행 시간메모리
422543MetalPowerFinancial Report (JOI21_financial)C++14
100 / 100
710 ms40360 KiB
#include <bits/stdc++.h>
using namespace std;

// Observation #1 : If D = N, this problem is LIS 
	// (supposedly we need to use segment tree)
	// (because of the additional constraints if D != N)

// However the D will not always be N
// Also there are some positions that we can't go to (because of the distance restriction)

// Observation #2 : But, it is not correct to assume that we can only jump to positions with relative distance <= D
	// Because we can use the positions with value < curr as "stepping stones"
	// The farthest position we can jump to can be found in O(N log N) using DSU and sorting
		// sort the numbers and add the positions if val < curr
		// Join two positions if the distance < D
		// the farthest position in the DSU is the farthest position we can jump - D
	// So now we can simplify the problem as LIS in a bounded range

// Observation #3 : We can solve this LIS in O(N log N) offline
	// solve the positions from the largest value
		// arr[curr] = rmq(curr + 1, curr + range[curr] + D) + 1
		// Note that we have to solve positions with large value from the left
		// Because we need indexes that have value < curr_value

// Observation #4 : the constraint p_{m} = N isn't important 
// because we can extend the LIS until p_{m} = N
	// if for example current p_{m} is A
	// We can add p_{m + 1} = A + 1, p_{m + 2} = A + 2, .. until p_{last} = N
	// Adding numbers will not decrease the impression score

// Supposedly AC with time complexity O(N log N)

#define pii pair<int, int>
#define fi first
#define se second

const int MX = 3e5 + 100;

inline void chmax(int& a, int b){
	if(b > a) a = b;
}

struct segtree{
	int seg[MX * 2];

	segtree(){
		memset(seg, 0, sizeof seg);
	}

	inline void upd(int p, int value){ // 0-based
		for(seg[p += MX] = value; p > 1; p >>= 1) seg[p >> 1] = max(seg[p], seg[p ^ 1]);
	}

	inline int range(int l, int r){ // 0-based [l, r]
		int res = 0;
		for(l += MX, r += MX + 1; l < r; l >>= 1, r >>= 1){
			if(l & 1) chmax(res, seg[l++]);
			if(r & 1) chmax(res, seg[--r]);
		}
		return res;
	}
} st;

struct disjoint_set{
	int par[MX], val[MX];

	disjoint_set(){
		for(int i = 0; i < MX; i++) val[i] = par[i] = i;
	}

	inline int f(int x){
		if(par[x] == x) return x;
		else return par[x] = f(par[x]);
	}

	inline void Join(int u, int v){
		int fu = f(u), fv = f(v);
		if(fu == fv) return;
		par[fu] = fv;
		chmax(val[fv], val[fu]);
	}

	inline int value(int x){
		return val[f(x)];
	}

} dsu;

int N, D, arr[MX], rg[MX], ans[MX];
vector<int> pos[MX];

int main(){
	ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);

	vector<int> v;

	cin >> N >> D;
	for(int i = 0; i < N; i++){
		cin >> arr[i]; v.push_back(arr[i]);
	}

	sort(v.begin(), v.end());
	v.resize(unique(v.begin(), v.end()) - v.begin());

	for(int i = 0; i < N; i++) arr[i] = lower_bound(v.begin(), v.end(), arr[i]) - v.begin();
	
	for(int i = 0; i < N; i++) pos[arr[i]].push_back(i);

	set<int> s; set<int>::iterator it;

	for(int i = 0; i < N; i++){
		for(auto& a : pos[i]){

			it = s.lower_bound(a);

			if(it != s.end() && (*it) - a <= D) dsu.Join(a, (*it));

			if(it != s.begin()){
				it--;
				if(a - (*it) <= D) dsu.Join(a, (*it));
			}

			s.insert(a);
		}

		for(auto& a : pos[i]){
			rg[a] = dsu.value(a);
		}
	}

	for(int i = N - 1; i >= 0; i--){
		for(auto& a : pos[i]){
			ans[a] = 1 + st.range(a + 1, min(N - 1, rg[a] + D));
			st.upd(a, ans[a]);
		}
	}

	int sol = 0;
	for(int i = 0; i < N; i++) chmax(sol, ans[i]);

	cout << sol << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...