/* 2002 MO P-I-1
 *
 * Petr Baudis
 * SEPTIMA, gymnazium Ad Fontes Jihlava
 *
 * Behem nacitani udaju postupne inicalizujeme pole list, do ktereho si
 * ukladame, kolik vetvi z daneho vetveni vychazi. Zaroven si inicializujeme i
 * pole children, kde si urzujeme pocet vetvi, ktere z vetveni vychazeji a
 * ktere jsme jiz nacetli - pritom pro kazde vetveni krome korene plati, ze uz
 * jsme nacetli jeho rodice, tudiz "nekorenne" polozky tohoto pole muzeme
 * inicializovat na jednicku. Posledni pole nazveme parents, v nem si ukladame
 * cisla rodicovskych vetveni (vyznam korenove polozky tohoto pole neni
 * definovan). Vzdy pak plati, ze zadani je korektni, pokud jsme byli schopni
 * najit odpovidajici rodicovske vetveni pro kazde vetveni, a pokud maji
 * vsechna vetveni obsazeny plny pocet vetvi. V opacnem pripade je pak zadani
 * nekorektni.
 *
 * Zbyva si jen rici, jak vlastne najdeme rodicovske vetveni - plati, ze nas
 * rodic je vzdy:
 *
 * a) predchozi vetveni, v pripade ze neni jiz zaplnene (coz plati v pripade
 * listu)
 *
 * b) rodicovske vetveni predchoziho veteni, v pripade ze neni jiz zaplnene a
 * pokud predchozi vetveni neni koren
 *
 * Takto postupne sestupujeme ve stromu smerem ke koreni, dokud nenajdeme
 * nejake volne mistecko nebo dokud na koren nenarazime (pokud neni volne
 * mistecko ani tam, zadani neni korektni).
 *
 * Pokud je zadani spravne, algoritmu se vzdy povede sestavit korektni strom
 * (zrejme z popisu algoritmu); pokud zadani spravne neni, algoritmu se to
 * naopak nemuze nikdy povest.
 *
 * Pametove naroky jsou O(N), staci nam tri pole velke N. Casove naroky jsou
 * take O(N) - sice pro hledani rodicu potrebujeme v nejhorsim pripade az N
 * iteraci, ale prave pro jedno vetveni (pro rodicovske vetveni to bude N-1
 * etc); naopak v opacnem pripade potrebujeme v N vetvenich pouze jedinou
 * iteraci. */

#include <stdio.h>
#include <stdlib.h>

void
nonexistent()
{
  FILE *f = fopen("caj.out", "w");

  if (!f) exit(3);
  fputs("NEEXISTUJE\n", f);
  fclose(f);
}

int
main()
{
  FILE *f;
  char buf[256];
  int i, n, *list, *parents, *children, last_parent = 0;

  f = fopen("caj.in", "r");
  if (!f) return 1;

  fgets(buf, 256, f);
  n = atoi(buf);

  list = calloc(n, sizeof(int));
  parents = calloc(n, sizeof(int));
  children = calloc(n, sizeof(int));
  if (!list || !parents || !children) return 2;

  for (i = 0; i < n; i++) {
    fscanf(f, "%d", &list[i]);

    /* Koren stromu je specialni, vsechno mame na nule a tak je to spravne. */
    if (i) {
      /* Vsechny nekoreny maji jako jeden konec rodice: */
      children[i] = 1;

      /* Zkusime si za rodice vzit rodice predchoziho prvku a postupne to
       * zkousime u dalsich a dalsich rodicu dokud nekde neni volne misto,
       * nebo... */
      while (children[last_parent] >= list[last_parent]) {
	/* ...dokud se nedostaneme az ke koreni... */
	if (!last_parent) {
	  /* ...v tom pripade to muzeme vzdat, tady uz mame smulu. */
	  fclose(f);
	  nonexistent();
	  return 0;
	}

	last_parent = parents[last_parent];
      }

      parents[i] = last_parent;

      /* Ale sem se vejdeme, hec! */
      children[parents[i]]++;

      /* Optimalizace: pokud jsme jenom list, nema cenu aby se na nas nekdo
       * zkousel nalepovat... */
      if (list[i] > 1) {
	/* ...ovsem jinak jen at si to zkusi. */
	last_parent = i;
      }
    }
  }

  fclose(f);

  /* Jenom zkontrolujeme, jestli nam nekde nezbyly neobsazena vetveni... */
  for (i = 0; i < n; i++) {
    /* ...to je totiz... */
    if (children[i] < list[i]) {
      /* ...moc moc spatne. */
      nonexistent();
      return 0;
    }
  }

  f = fopen("caj.out", "w");
  if (!f) return 3;
  fputs("EXISTUJE\n", f);
  fclose(f);
  return 0;
}
