Cod sursa(job #1016750)

Utilizator sleepaholicNeculaescu Theodor sleepaholic Data 26 octombrie 2013 18:26:08
Problema Secv8 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 7.04 kb
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <ctime>
#include <algorithm>

using namespace std;

#define MAX_BUCK 1024
#define MAX_NR 1700000

struct Bucket {
   bool bReverse;
   int *a, nrElem;

   Bucket() {
      bReverse = false;
      nrElem = 0;
      a = NULL;
   }

   void clear() {
      nrElem = 0;
      bReverse = false;
   }

   void reset() {
      if (bReverse) {
         bReverse = false;
         reverse(a, a + nrElem);
      }
   }

   int getPoz(int k) {
      if (!bReverse) {
         return k;
      } else {
         return nrElem - k - 1;
      }
   }

   void reversePartial(int st, int fn) {
      st = getPoz(st);
      fn = getPoz(fn);
      if (st > fn) {
         swap(st, fn);
      }
      reverse(a + st, a + fn + 1);
   }

   int deleteRange(int st, int fn) {
      st = getPoz(st);
      fn = getPoz(fn);
      if (st > fn) {
         swap(st, fn);
      }
      if (fn + 1 < nrElem) {
         memmove(a + st, a + fn + 1, sizeof(int) * (nrElem - fn - 1));
      }
      nrElem -= (fn - st + 1);
      return fn - st + 1;
   }

   int getElem(int k) {
      return a[getPoz(k)];
   }

   void insert(int poz, int val) {
      poz = getPoz(poz);
      if (bReverse) {
         poz++;
      }
      memmove(a + poz + 1, a + poz, sizeof(int) * (nrElem - poz));
      a[poz] = val;
      nrElem++;
   }

   void print() {
      if (!bReverse) {
         for (int i = 0; i < nrElem; i++) {
            printf("%d ", a[i]);
         }
      } else {
         for (int i = nrElem - 1; i >= 0; i--) {
            printf("%d ", a[i]);
         }
      }
   }

   void mergeWith(Bucket &b) {
      if (bReverse && b.bReverse) {
         memmove(a + b.nrElem, a, sizeof(int) * nrElem);
         memcpy(a, b.a, sizeof(int) * b.nrElem);
      } else {
         if (bReverse) {
            bReverse = false;
            reverse(a, a + nrElem);
         }
         memcpy(a + nrElem, b.a, sizeof(int) * b.nrElem);
         if (b.bReverse) {
            reverse(a + nrElem, a + nrElem + b.nrElem);
         }
      }
      nrElem += b.nrElem;
      b.clear();
   }
};

int nrBuckets = 1;
Bucket buckets[MAX_NR / MAX_BUCK], bTemp;

int getBucket(int &poz) {
   int b = 0;
   while (b + 1 < nrBuckets && buckets[b].nrElem <= poz) {
      poz -= buckets[b++].nrElem;
   }
   return b;
}

void insertBucket(int poz, Bucket bTemp) {
   memmove(buckets + poz + 1, buckets + poz, sizeof(Bucket) * (nrBuckets - poz));
   buckets[poz] = bTemp;
   if (buckets[poz].a == NULL) {
      buckets[poz].a = new int[MAX_BUCK];
   }
   nrBuckets++;
}

int GetElement(int poz) {
   int b = getBucket(poz);
   return buckets[b].getElem(poz);
}

void InsertElem(int poz, int val) {
   int b = getBucket(poz);
   buckets[b].insert(poz, val);
   if (buckets[b].nrElem == MAX_BUCK) {
      buckets[b].reset();
      insertBucket(b + 1, buckets[nrBuckets]);
      const int mij = MAX_BUCK / 2;
      memcpy(buckets[b + 1].a, buckets[b].a + mij, sizeof(int) * mij);
      buckets[b + 1].nrElem = buckets[b].nrElem = mij;
   }
}

void DeleteRange(int st, int fn) {
   int bFirst = getBucket(st);
   int bLast = getBucket(fn);
   if (bFirst == bLast) {
      buckets[bFirst].deleteRange(st, fn);
      return;
   }
   buckets[bFirst].deleteRange(st, buckets[bFirst].nrElem - 1);
   for (int b = bFirst + 1; b < bLast; b++) {
      buckets[b].clear();
   }
   buckets[bLast].deleteRange(0, fn);
}

void CheckBucketMerge(int bFirst) {
   if (bFirst > 0 && buckets[bFirst - 1].nrElem + buckets[bFirst].nrElem < (int)(MAX_BUCK * 0.7)) {
      buckets[bFirst - 1].mergeWith(buckets[bFirst]);
      nrBuckets--;
      Bucket bTemp = buckets[bFirst];
      memmove(buckets + bFirst, buckets + bFirst + 1, (nrBuckets - bFirst) * sizeof(Bucket));
      buckets[nrBuckets] = bTemp;
   }
}

void ReverseRange(int st, int fn) {
   int bFirst = getBucket(st);
   int bLast = getBucket(fn);

   if (bFirst == bLast) {
      buckets[bFirst].reversePartial(st, fn);
      return;
   }
   buckets[bFirst].reset();
   buckets[bLast].reset();

   if (bFirst == 0 || st + buckets[bFirst - 1].nrElem >= MAX_BUCK) {
      insertBucket(bFirst, buckets[nrBuckets]);
      bFirst++;
      bLast++;
   }

   buckets[bFirst - 1].reset();
   memcpy(buckets[bFirst - 1].a + buckets[bFirst - 1].nrElem, buckets[bFirst].a, sizeof(int) * st);
   buckets[bFirst - 1].nrElem += st;
   buckets[bFirst].nrElem -= st;
   memmove(buckets[bFirst].a, buckets[bFirst].a + st, sizeof(int) * buckets[bFirst].nrElem);

   const int nrEnd = buckets[bLast].nrElem - fn - 1;
   if (bLast + 1 == nrBuckets || buckets[bLast + 1].nrElem + nrEnd >= MAX_BUCK) {
      insertBucket(bLast + 1, buckets[nrBuckets]);
   }

   buckets[bLast + 1].reset();
   memmove(buckets[bLast + 1].a + nrEnd, buckets[bLast + 1].a, sizeof(int) * buckets[bLast + 1].nrElem);
   memcpy(buckets[bLast + 1].a, buckets[bLast].a + fn + 1, sizeof(int) * nrEnd);
   buckets[bLast + 1].nrElem += nrEnd;
   buckets[bLast].nrElem -= nrEnd;

   reverse(buckets + bFirst, buckets + bLast + 1);
   for (int b = bFirst; b <= bLast; b++) {
      buckets[b].bReverse = !buckets[b].bReverse;
   }

   CheckBucketMerge(bFirst);
   CheckBucketMerge(bLast);
}

int A[300000], nrElem = 0;

void insertBrute(int poz, int k) {
   memmove(A + poz + 1, A + poz, sizeof(int) * (nrElem - poz));
   A[poz] = k;
   nrElem++;
}

void deleteBrute(int st, int fn) {
   if (fn + 1 < nrElem) {
      memmove(A + st, A + fn + 1, sizeof(int) * (nrElem - fn));
   }
   nrElem -= (fn - st + 1);
}

void reverseBrute(int st, int fn) {
   reverse(A + st, A + fn + 1);
}

int main() {
   freopen("secv8.in", "rb", stdin);
   freopen("secv8.out", "wb", stdout);
   int M, ignore;
   scanf("%d %d\n", &M, &ignore);
   buckets[0].a = new int[MAX_BUCK];

   double start = clock();

   while (M--) {
      //fprintf(stderr, "%d\n", M);
      char op;
      int st, fn, poz, val;
      scanf("%c", &op);
      if (op == 'A') {
         scanf("%d\n", &poz); poz--;
         //int ans = GetElement(poz);
         //if (ans != A[poz]) {
         //   ans = GetElement(poz);
         //   fprintf(stderr, "Dif!!\n");
         //}
         printf("%d\n", GetElement(poz));
      } else
      if (op == 'I') {
         scanf("%d %d\n", &poz, &val);
         poz--;
         InsertElem(poz, val);
         //insertBrute(poz, val);
      } else {
         scanf("%d %d\n", &st, &fn);
         st--; fn--;
         if (op == 'D') {
            DeleteRange(st, fn);
            //deleteBrute(st, fn);
         } else {
            ReverseRange(st, fn);
            //reverseBrute(st, fn);
         }
      }

      //for (int i = 0; i < nrElem; i++) {
      //   if (A[i] != GetElement(i)) {
      //      fprintf(stderr, "WA\n");
      //   }
      //}
   }
   for (int i = 0; i < nrBuckets; i++) {
      buckets[i].print();
   }

   fprintf(stderr, "%.3f ms\n", (clock() - start) / CLOCKS_PER_SEC);
   return 0;
}