Submission #638372

#TimeUsernameProblemLanguageResultExecution timeMemory
638372LeticiaFCSFinancial Report (JOI21_financial)C++17
48 / 100
4102 ms56668 KiB
#include "bits/stdc++.h"
#define st first
#define nd second
using lint = int64_t;
constexpr int MOD = int(1e9) + 7;
constexpr int INF = 0x3f3f3f3f;
constexpr int NINF = 0xcfcfcfcf;
constexpr lint LINF = 0x3f3f3f3f3f3f3f3f;
const long double PI = acosl(-1.0);
// Returns -1 if a < b, 0 if a = b and 1 if a > b.
int cmp_double(double a, double b = 0, double eps = 1e-9) {
	return a + eps > b ? b + eps > a ? 0 : 1 : -1;
}
using namespace std;

struct UF {
	vector<int> e, mini;
	UF(int n) : e(n, -1), mini(n) {
		iota(mini.begin(), mini.end(), 0);
	}
	bool same_set(int a, int b) { return find(a) == find(b); }
	int size(int x) { return -e[find(x)]; }
	int find(int x) { return e[x] < 0 ? x : e[x] = find(e[x]); }
	int minimum(int x){ return mini[find(x)]; }
	bool unite(int a, int b) {
		a = find(a), b = find(b);
		if (a == b) return 0;
		if (e[a] > e[b]) swap(a, b);
		e[a] += e[b]; e[b] = a;
		mini[a] = min(mini[a], mini[b]);
		return 1;
	}
};


struct segtree{
	vector<int> tree;
	segtree(int n) : tree(4*n + 1, -1) {};
	int query(int l, int r, int id, int lq, int rq){
		if(rq <= l || r <= lq) return -1;
		if(lq <= l && r <= rq) return tree[id];
		int mid = (l+r)/2;
		return max(query(l, mid, 2*id, lq, rq), query(mid, r, 2*id + 1, lq, rq));
	}
	void update(int l, int r, int id, int x, int val){		
		if(x < l || x >= r) return;
		if(l + 1 == r){
			tree[id] = val;		
			return;
		}		
		
		int mid = (l+r)/2;
		update(l, mid, 2*id, x, val);
		update(mid, r, 2*id + 1, x, val);
		tree[id] = max(tree[2*id], tree[2*id+1]);
	}
	int query(int l, int r){
		return query(0, int(tree.size()/4), 1, l, r);
	}
	void update(int x, int val){
		update(0, int(tree.size()/4), 1, x, val);
	}
};

int main() {
	cin.tie(nullptr)->sync_with_stdio(false);
	int n, d;
	cin>>n>>d;
	UF uf(n+1);
	segtree seg(n+1);
	vector<int> a(n+1);
	vector<int> dp(n+1, -1);
	dp[0] = 0; 
	seg.update(0, 0);
	//dp[i] <-- max se i é o último e i > atrás
	map<int,vector<int>> idOfVal;
	for(int i=1; i<=n; i++){
		cin>>a[i];
		idOfVal[a[i]].push_back(i);
	}
	set<int> visited;
	visited.insert(0);

	
	for(auto &[x, ids]: idOfVal){
		reverse(ids.begin(), ids.end());
		for(int id: ids){
			auto nxt = visited.upper_bound(id); 
			if(nxt != visited.end()){
				if((*nxt) - id <= d)
					uf.unite(id, *nxt);
			}
			if(nxt != visited.begin()){
				auto before = nxt;
				before--;
				if(id - (*before) <= d)
					uf.unite(id, *before);
			}
			visited.insert(id);
					
			//cerr<<"id "<<id<<"\n";
			dp[id] = 1;
			
			int l = uf.minimum(id);
			for(int j = id-1; j>=l; j--){
				if(dp[j] != -1){
				//	cerr<<"j "<<j<<"\n";
					dp[id] = max(dp[id], 1 + dp[j]); 
				} 
			} 
			
	//		dp[id] = 1 + max(0, seg.query(l, id));
			seg.update(id, dp[id]);
		}
	}
	cout<<*max_element(dp.begin(), dp.end())<<"\n";
	//j > max before

	return 0;
}
/*
[  ]Leu o problema certo???
[  ]Ver se precisa de long long
[  ]Viu o limite dos fors (é n? é m?)
[  ]Tamanho do vetor, será que é 2e5 em vez de 1e5??
[  ]Testar sample
[  ]Testar casos de  borda
[  ]1LL no 1LL << i
[  ]Testar mod (é 1e9+7, mesmo?, será que o mod não ficou negativo?)
*/
#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...