单旋递归大常数splay

show show我的单旋递归大常数splay。

很蛋疼的rotate把lc和rc两个数组进去了。

题目:2010省队集训,unstable不稳定匹配。


#include 
#include 
#include 
#include 
#include 
#include 

#define maxn 1150000
#define maxm 1150000
#define prime 1000000007ll
#define unit 13499267949257065399ull
#define maxrange 11000

typedef unsigned long long ull;

typedef struct
{
  int size, rev;
  ull key, hfor, hbak;
} node;

ull dest[maxm];
node x[maxn];
int lc[maxn];
int rc[maxn];
ull R[maxrange];
ull U[maxn];
ull P[maxn];
int *ptr[2] = {lc, rc};
int n, m, root, xtop;

inline void update (int p)
{
  node *y = x + p, *l = x + lc[p], *r = x + rc[p];
  y->size = l->size + r->size + 1;
  y->hfor = l->hfor + P[l->size] * y->key + P[l->size + 1] * r->hfor;
  y->hbak = r->hbak + P[r->size] * y->key + P[r->size + 1] * l->hbak;
}

inline void swap (int *i, int *j){int t = *i; *i = *j; *j = t;}
inline void swapull (ull *i, ull *j){ull t = *i; *i = *j; *j = t;}
inline int min (int i, int j){return i < j ? i : j;}
inline ull hash (int l, int r){return (dest[r] - dest[l]) * U[l];}

inline void mark_rev (int p)
{
  swap (&lc[p], &rc[p]);
  swapull (&x[p].hfor, &x[p].hbak);
  x[p].rev ^= 1;
}

inline void push_rev (int p)
{
  mark_rev (lc[p]), mark_rev (rc[p]), x[p].rev = 0;
}

void rotate (int *t, int *lc, int *rc)
{
  int k = lc[*t];
  lc[*t] = rc[k];
  rc[k] = *t;
  update (*t);
  *t = k;
}

void splay (int *t, int k)
{
  if (x[*t].rev)
    push_rev (*t);
  int s = x[lc[*t]].size;
  if (s > k)
    splay (lc + *t, k), rotate (t, lc, rc);
  else if (s < k)
    splay (rc + *t, k - s - 1), rotate (t, rc, lc);
}

inline void inteval (int l, int r){splay (&root, r + 1), update (root), splay (&root, l - 1), update (root);}

int query (int A, int B)
{
  --A, --B;
  splay (&root, A), update (root);
  int t = rc[root], s, ret = 0;
  for (; t; )
    {
      if (x[t].rev)
        push_rev (t);
      s = x[lc[t]].size + 1;
      if (B + s <= m && x[lc[t]].hfor + P[s - 1] * x[t].key == hash (B, B + s))
        ret += s, t = rc[t], B += s;
      else
        t = lc[t];
    }
  return ret;
}

int build (int l, int r)
{
  int mid = (l + r) >> 1, t = mid + 2;
  if (l != mid) lc[t] = build (l, mid - 1);
  if (r != mid) rc[t] = build (mid + 1, r);
  update (t);
  return t;
}

int main()
{
  FILE *fin  = fopen ("unstable.in" , "r");
  FILE *fout = fopen ("unstable.out", "w");

  int i, s1, s2, s3, s4, k, p;
  char cmd[50];

  srand (time (0));
  for (i = 0; i < maxrange; ++i)
    R[i] = (ull)rand () << 32 | rand ();
  for (P[0] = U[0] = 1, i = 1; i < maxm; ++i)
    P[i] = P[i - 1] * prime, U[i] = U[i - 1] * unit;
  
  fscanf (fin, "%d%d", &n, &m);
  for (i = 1; i <= n; ++i)
    fscanf (fin, "%d", &s1), x[i + 2] = (node){1, 0, R[s1]};
  for (i = 1; i <= m; ++i)
    fscanf (fin, "%d", &s1), dest[i] = dest[i - 1] + R[s1] * P[i - 1];

  root = 1, xtop = n + 2;
  rc[1] = 2, lc[2] = build (1, n), update (2), update (1);
  fscanf (fin, "%d%d%d%d", &s1, &s2, &s3, &s4);
  inteval (1, 1);
  for (i = s1 + s2 + s3 + s4; i; --i)
    {
      fscanf (fin, "%s", cmd);
      switch (cmd[0])
        {
        case 'I':
          fscanf (fin, "%d%d", &k, &p);
          inteval (k, k - 1), x[++xtop] = (node){1, 0, R[p], R[p], R[p]};
          lc[rc[root]] = xtop; break;
        case 'D':
          fscanf (fin, "%d", &k);
          inteval (k, k), lc[rc[root]] = 0; break;
        case 'R':
          fscanf (fin, "%d%d", &k, &p);
          if (k > p) swap (&k, &p);
          inteval (k, p);
          mark_rev (lc[rc[root]]); break;
        case 'Q':
          fscanf (fin, "%d%d", &k, &p);
          fprintf (fout, "%d\n", query (k, p));
          break;
        }
      update (rc[root]), update (root);
    }
  fclose (fin);
  fclose (fout);
  return 0;
}




你可能感兴趣的:(OI,build,cmd,query,file,struct,2010)