Submission #130362

#TimeUsernameProblemLanguageResultExecution timeMemory
130362cjoaMechanical Doll (IOI18_doll)C++11
85.55 / 100
244 ms14580 KiB
#include "doll.h"
 
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>
#include <cstdio>
 
using namespace std;
 
 
namespace TreeSol {
 
typedef vector<int> VI;
 
const int UNDEFINED = 999999;

struct Node {
   int L, R;
   int id;
   bool flipped, leaf;
   Node(int _L = -1, int _R = -1, int _id = UNDEFINED)
      : L(_L), R(_R), id(_id), flipped(false), leaf(false) {}
};
 
vector<Node> nodes;

void build_tree(int idx, int L, int R) {
   if (L == R) {
      nodes[idx] = Node(L, R);
      nodes[idx].leaf = true;
      return;
   }
   int mid = (L+R)/2;
   nodes[idx] = Node(L, R, -idx);
   build_tree(idx*2, L, mid);
   build_tree(idx*2+1, mid+1, R);
}
 
void assign_device_id(int id, int from, int idx = 1) {
   if (nodes[idx].L == nodes[idx].R) {
      if (nodes[idx].L >= from)
         nodes[idx].id = id;
      else {
         nodes[idx].id = -1;
         assign_device_id(id, from);
      }
      return;
   }
   nodes[idx].flipped = !nodes[idx].flipped;
   if (nodes[idx].flipped)
      assign_device_id(id, from, 2*idx);
   else
      assign_device_id(id, from, 2*idx+1);
}

void compress_tree(int idx = 1) {
    if (nodes[idx].L == nodes[idx].R)
       return;

    compress_tree(idx*2);
    compress_tree(idx*2 + 1);
    if (nodes[idx*2].leaf && nodes[idx*2+1].leaf && 
        nodes[idx*2].id == nodes[idx*2+1].id) {
        nodes[idx].leaf = true;
        nodes[idx].id = nodes[idx*2].id;
    }
}

void reassign_switch_ids(map<int,int>& reassigned_ids,
                         int& last_switch_id, int idx = 1) {
    int id = nodes[idx].id;
    if (id < 0) {
        if (reassigned_ids.count(id))
            nodes[idx].id = reassigned_ids[id];
        else {
            last_switch_id++;
            nodes[idx].id = reassigned_ids[id] = -last_switch_id;
        }
    }
    if (nodes[idx].leaf)
        return;
    if (nodes[idx].L == nodes[idx].R)
       return;
    reassign_switch_ids(reassigned_ids, last_switch_id, idx*2);
    reassign_switch_ids(reassigned_ids, last_switch_id, idx*2 + 1);
}


struct Switch {
   int x, y;
};
vector<Switch> switches;

void assign_switch_exits(int idx = 1) {
   if (nodes[idx].L < 0) return;
   if (nodes[idx].leaf) return;
   int id = nodes[idx].id;
   if (id < 0) {
      id = -(id+1);
      switches[ id ].x = nodes[idx*2  ].id;
      switches[ id ].y = nodes[idx*2+1].id;
   }
   assign_switch_exits(idx*2);
   assign_switch_exits(idx*2 + 1);
}


int build_circuit(int src, const VI& nxt) {
   int K = nxt.size();
   if (K == 1)
      return nxt[0];

   if (count(nxt.begin(), nxt.end(), nxt[0]) == K)
      return nxt[0];
 
   int nodes_last_level = 1;
   while (nodes_last_level < K)
      nodes_last_level *= 2;
 
   nodes = vector<Node>(2*nodes_last_level);

   build_tree(1, 0, nodes_last_level-1);
 
   int from = nodes_last_level - K;
   for (int dev_id : nxt)
      assign_device_id(dev_id, from);

   /*
   fprintf(stderr, "src: %d\n", src);
   fprintf(stderr, "nodes_last_level:%d  K:%d\n", nodes_last_level, K);
   */

   /*
   fprintf(stderr, "After assigned device ids\n");
   for (int idx = 1; idx < int(nodes.size()); ++idx) {
      Node x = nodes[idx];
      fprintf(stderr, "%3d  [%d,%d]  id:%d  leaf:%d\n", idx, x.L, x.R, x.id, x.leaf);
   }
   fprintf(stderr, "\n");
   */
 
   compress_tree();

   /*
   fprintf(stderr, "After compression\n");
   for (int idx = 1; idx < int(nodes.size()); ++idx) {
      Node x = nodes[idx];
      fprintf(stderr, "%3d  [%d,%d]  id:%d  leaf:%d\n", idx, x.L, x.R, x.id, x.leaf);
   }
   fprintf(stderr, "\n");
   */

   int last_switch_id = switches.size();
   map<int,int> reassigned_ids;
   reassign_switch_ids(reassigned_ids, last_switch_id);

   /*
   fprintf(stderr, "After reassignment\n");
   for (int idx = 1; idx < int(nodes.size()); ++idx) {
      Node x = nodes[idx];
      fprintf(stderr, "%3d  [%d,%d]  id:%d  leaf:%d\n", idx, x.L, x.R, x.id, x.leaf);
   }
   fprintf(stderr, "\n");
   */

   // fprintf(stderr, "last_switch_id:%d\n", last_switch_id);
   switches.resize( last_switch_id );

   assign_switch_exits();
   // fprintf(stderr, "END\n\n"); 

   return nodes[1].id;
}
 
}
 
void create_circuit(int M, std::vector<int> A) {
   int N = A.size();
 
   vector< vector<int> > nxt(M+1);
   for (int i = 1; i < N; ++i)
      nxt[ A[i-1] ].push_back( A[i] );
   nxt[ A.back() ].push_back(0);
 
   vector<int> C(M + 1);
   C[0] = A[0];
 
   for (int i = 1; i <= M; ++i) {
      if (nxt[i].empty()) continue;
      C[i] = TreeSol::build_circuit(i, nxt[i]);
   }
 
   int S = TreeSol::switches.size();
   vector<int> X(S), Y(S);
   for (int j = 0; j < S; ++j) {
      X[j] = TreeSol::switches[j].x;
      Y[j] = TreeSol::switches[j].y;
   // fprintf(stderr, "j:%d  x:%d  y:%d\n", j, X[j], Y[j]);
   }
   answer(C, X, Y);
 
}


#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...