#include #include #include #include #include #include using namespace std; const int MAXN = 2000000; int N; ifstream fr; ofstream fw; static int altezza[MAXN]; int lep[MAXN]; // fissato i, lep[i] contiene l'indice dell'albero più a sinistra // distrutto dall'abbattimento di i int rep[MAXN]; // fissato i, rep[i] contiene l'indice dell'albero più a destra // distrutto dall'abbattimento di i int memo[MAXN]; int first_tree[MAXN]; bool direzione[MAXN]; int n_candidati; int candidati[MAXN]; int min_candidati[MAXN]; static char intbuf[32]; void Abbatti(int indice, int direzione) { int i, len = sprintf(intbuf, "%d %d\n", indice, direzione); for (i=0; i= 0 && i - j < H[i]) j = lep[j] - 1; lep[i] = j + 1; } rep[N-1] = N-1; for (int i = N-2; i >= 0; i--) { int j = i + 1; while (j < N && j - i < H[i]) j = rep[j] + 1; rep[i] = j - 1; } int j, test; for (int i = 0; i < N; i++) { // Primo caso: butto i a sinistra j = lep[i] - 1; test = 1; if (j >= 0) test += memo[j]; memo[i] = test; first_tree[i] = i; direzione[i] = false; // Secondo caso: abbatto a destra un albero che abbatte i nella caduta while (n_candidati && rep[*(candidati + n_candidati - 1)] < i) --n_candidati; if (n_candidati) { j = min_candidati[n_candidati - 1] - 1; test = 1; if (j >= 0) test += memo[j]; if (test < memo[i]) { memo[i] = test; first_tree[i] = j + 1; direzione[i] = true; } } j = i; if (n_candidati) { if ( min_candidati[n_candidati - 1] == 0 || memo[min_candidati[n_candidati - 1] - 1] < memo[i - 1] ) { j = min_candidati[n_candidati - 1]; } } ++n_candidati; candidati[n_candidati - 1] = i; min_candidati[n_candidati - 1] = j; } // Ricostruisci la soluzione int i = N - 1; while (i >= 0) { Abbatti(first_tree[i], direzione[i]); if (direzione[i] == false) // A sinistra i = lep[i] - 1; else i = first_tree[i] - 1; } } int main(){ fr.open("input.txt"); assert(fr); fw.open("output.txt"); assert(fw); fr >> N; for (int i=0; i> altezza[i]; Pianifica(N, altezza); fr.close(); fw.close(); return 0; }