Cod sursa(job #1567610)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 13 ianuarie 2016 16:41:51
Problema Arbore Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.77 kb
#include <cstdio>
#include <cstring>
#include <bitset>
#include <ctime>
#include <random>

#define MaxN 100050
#define MaxS 1000050
#define BUCKET 500
#define MaxBuckets 410
#define NIL -1

#define RANDOM_PASS 100

using namespace std;

struct Edge {
   int v;
   int next;
};

Edge l[2 * (MaxN - 1)];
int adj[MaxN];
int sum[2 * MaxN + BUCKET];

bitset <MaxS + 2> H[MaxBuckets];
int lazy[MaxBuckets];
int euler[2 * MaxN];
pair <int, int> node2Euler[MaxN];
int ptr;

int numBuckets;

static inline void addEdge(const int &u, const int &v, const int &pos) {
   l[pos].v =v;
   l[pos].next = adj[u];
   adj[u] = pos;
}

void DFS(int u, int parent) {
   euler[ptr] = u;
   node2Euler[u].first = ptr++;
   for (int i = adj[u]; i != NIL; i = l[i].next) {
      if (l[i].v != parent) {
         DFS(l[i].v, u);
      }
   }
   euler[ptr] = u;
   node2Euler[u].second = ptr++;
}

static inline int getRandom(void) {
   static mt19937 gen(time(0));
   int x = gen();
   return x < 0 ? -x : x;
}

static inline int randomCheck(const int &need) {
   for (int i = 0; i < RANDOM_PASS; i++) {
      int bucket = getRandom() % (numBuckets + 1);

      if (need - lazy[bucket] >= 0 && H[bucket][need - lazy[bucket]]) {
         return bucket;
      }
   }
   return -1;
}

int main() {
   freopen("arbore.in", "r", stdin);
   freopen("arbore.out", "w", stdout);
   int N, Q;
   int u, v;
   int opType, add;

   scanf("%d%d", &N, &Q);
   memset(adj, NIL, 4 * N);
   for (int i = 1; i < N; i++) {
      scanf("%d%d", &u, &v);
      addEdge(u - 1, v - 1, 2 * i - 2);
      addEdge(v - 1, u - 1, 2 * i - 1);
   }

   DFS(0, -1);
   numBuckets = -1;
   for (int i = 0; i < ptr; i++) {
      numBuckets += (i == i / BUCKET * BUCKET);
      H[numBuckets][0] = 1;
   }

   while (ptr != ptr / BUCKET * BUCKET) {
      sum[ptr++] = MaxS + 1;
   }

   while (Q--) {
      scanf("%d", &opType);
      if (opType == 1) {
         scanf("%d%d", &u, &add); u--;

         int bucket = node2Euler[u].first / BUCKET;
         int startBucket = bucket * BUCKET;
         int endBucket = startBucket + BUCKET;

         for (int i = startBucket; i < endBucket; i++) {
            H[bucket][sum[i]] = 0;
         }
         for (int i = node2Euler[u].first; (i < endBucket) && (i <= node2Euler[u].second); i++) {
            sum[i] += add;
         }
         for (int i = startBucket; i < endBucket; i++) {
            H[bucket][sum[i]] = 1;
         }

         if (node2Euler[u].second / BUCKET != bucket) {
            int fnBucket = node2Euler[u].second / BUCKET;
            for (int i = bucket + 1; i < fnBucket; i++) {
               lazy[i] += add;
            }
            startBucket = fnBucket * BUCKET;
            endBucket = startBucket + BUCKET;
            for (int i = startBucket; i < endBucket; i++) {
               H[fnBucket][sum[i]] = 0;
            }
            for (int i = startBucket; i <= node2Euler[u].second; i++) {
               sum[i] += add;
            }
            for (int i = startBucket; i < endBucket; i++) {
               H[fnBucket][sum[i]] = 1;
            }
         }
      } else {
         scanf("%d", &add);

         int bucket = randomCheck(add);

         if (bucket == -1) {
            do {
               bucket++;
            } while (bucket <= numBuckets && (add - lazy[bucket] < 0 || !H[bucket][add - lazy[bucket]]));
         }

         if (bucket <= numBuckets) {
            add -= lazy[bucket];
            bucket *= BUCKET;
            while (sum[bucket] != add) {
               bucket++;
            }
            printf("%d\n", 1 + euler[bucket]);
         } else {
            puts("-1");
         }
      }
   }
   fclose(stdin);
   fclose(stdout);
   return 0;
}