块状链表实在难写,反正没一次写对的,于是我用Treap来Cheat呵呵,其实Treap的话呢,插入删除和打印操作都是O(nlogL)(n:操作数的长度,L:总长度)的,比起块状链表华丽丽的O(sqrt(n))来啊那可是大大的不美,所以在时间上的差距也很明显(6倍啊OTZ),不过还是AC了,嗯。话说Treap比起朴素的数组实现来说,最大的优势在于LogL上。如果把LogL看成是常数,那么这个插入删除的总复杂度几乎可以看成是O(L)的,其实还是很好的,因为单单把数据读进去就要O(L)的复杂度。朴素的实现,插入或删除是O(n+L)的,积累起来最坏O(L^2),而Treap来说最坏情况期望是O(LlogL),虽然很Cheat,不过还是很有内涵的Cheat。

最近写Treap写得越来越顺手,估计真正比赛的时候如果遇上Treap的题应该也能写对。

从思想上来说呢,把序列存在Treap里头确实不太自然。其实很简单,只要把序列想象成一个个离散的元素加上一个位置标号,然后按照位置标号排序得到的有序队列就可以了。然后按照那个位置标号建立平衡树,就能在平衡树上实现串的操作了。

于是把程序和时间比较贴出来,asdf是HQM的标程。

开始测试 asdf
   正在编译 asdf.editor ...成功
      正在测试 asdf.editor.0(editor0.in)... 正确 0.308秒 得分: 10
      正在测试 asdf.editor.1(editor1.in)... 正确 0.003秒 得分: 10
      正在测试 asdf.editor.2(editor2.in)... 正确 0.072秒 得分: 10
      正在测试 asdf.editor.3(editor3.in)... 正确 0.085秒 得分: 10
      正在测试 asdf.editor.4(editor4.in)... 正确 0.085秒 得分: 10
      正在测试 asdf.editor.5(editor5.in)... 正确 0.047秒 得分: 10
      正在测试 asdf.editor.6(editor6.in)... 正确 0.053秒 得分: 10
      正在测试 asdf.editor.7(editor7.in)... 正确 0.050秒 得分: 10
      正在测试 asdf.editor.8(editor8.in)... 正确 0.138秒 得分: 10
      正在测试 asdf.editor.9(editor9.in)... 正确 0.258秒 得分: 10
      asdf.editor 的总分: 100
   asdf 的总分: 100
开始测试 ti
   正在编译 ti.editor ...成功
      正在测试 ti.editor.0(editor0.in)... 正确 1.771秒 得分: 10
      正在测试 ti.editor.1(editor1.in)... 正确 0.003秒 得分: 10
      正在测试 ti.editor.2(editor2.in)... 正确 0.663秒 得分: 10
      正在测试 ti.editor.3(editor3.in)... 正确 0.743秒 得分: 10
      正在测试 ti.editor.4(editor4.in)... 正确 0.734秒 得分: 10
      正在测试 ti.editor.5(editor5.in)... 正确 0.524秒 得分: 10
      正在测试 ti.editor.6(editor6.in)... 正确 0.526秒 得分: 10
      正在测试 ti.editor.7(editor7.in)... 正确 0.518秒 得分: 10
      正在测试 ti.editor.8(editor8.in)... 正确 0.668秒 得分: 10
      正在测试 ti.editor.9(editor9.in)... 正确 0.920秒 得分: 10
      ti.editor 的总分: 100
   ti 的总分: 100
 

 

#include <cstdio>
#include <cstdlib>
#include <cstring>

FILE *in =fopen("editor.in", "r");
FILE *out =fopen("editor.out", "w");

typedef struct node
{
  int k, size;
  char ch;
  node *l, *r;
} node;

node *t, *nul;
int cursor=1;

node *Right_Rotate(node *t)
{
  t->l->size=t->size;
  t->size=t->l->r->size+1+t->r->size;
  node *t2=t->l;
  t->l=t2->r;
  t2->r=t;
  t=t2;
  return t;
}

node *Left_Rotate(node *t)
{
  t->r->size=t->size;
  t->size=t->r->l->size+1+t->l->size;
  node *t2=t->r;
  t->r=t2->l;
  t2->l=t;
  t=t2;
  return t;
}

node *Insert2(node *t, int num, char ch)
{
  if (t==nul)
  {
    t=(node*) malloc(sizeof(node));
    t->l=t->r=nul;
    t->k=rand();
    t->ch=ch;
    t->size=1;
    return t;
  }
  else
  {
    t->size++;
    t->r=Insert2(t->r, num, ch);
    if (t->r->k>t->k) t=Left_Rotate(t);
    return t;
  }
}

node *Insert(node *t, int num, char ch)
{
  if (t==nul) return Insert2(t, num, ch);
  if (t->l->size>=num)
  {
    t->size++;
    t->l=Insert(t->l, num, ch);
    if (t->l->k>t->k) t = Right_Rotate(t);
    return t;
  }
  else
    if (t->l->size+1<num)
    {
      t->size++;
      t->r=Insert(t->r, num-t->l->size-1, ch);
      if (t->r->k>t->k) t=Left_Rotate(t);
      return t;
    }
    else
    {
      t->size++;
      t->l=Insert2(t->l, num, ch);
      return t;
    }
}

node *Delete(node *t)
{
  if (t->l==t->r&&t->r==nul)
  {
    free(t);
    return nul;
  }
  else
    if (t->l->k>t->r->k)
    {
      t->size--;
      t=Right_Rotate(t);
      t->r=Delete(t->r);
      return t;
    }
    else
    {
      t->size--;
      t=Left_Rotate(t);
      t->l=Delete(t->l);
      return t;
    }
}

void Clear(node *t)
{
  if (t==nul) return;
  Clear(t->l);
  Clear(t->r);
  free(t);
}

node *Delete(node *t, int st, int ed)
{
  if (st>ed) return t;
  if (t->l->size+1<st)
  {
    t->size-=(ed-st+1);
    t->r=Delete(t->r, st-(t->l->size+1), ed-(t->l->size+1));
    return t;
  }
  else
    if (t->l->size+1==st)
    {
      t=Delete(t);
      return Delete(t, st, ed-1);
    }
    else
      if (st==1&&ed==t->size)
      {
        Clear(t);
        return nul;
      }
      else
        if (ed<=t->l->size)
        {
          t->size-=ed-st+1;
          t->l=Delete(t->l, st, ed);
          return t;
        }
        else
        {
          t->size-=ed-st;
          int l=t->l->size-st+1;
          t->l=Delete(t->l, st, t->l->size);
          t->r=Delete(t->r, 1, (ed-st+1)-l-1);
          t=Delete(t);
          return t;
        }
}

void Print(node *t, int st, int ed)
{
  if (st>ed) return;
  if (t==nul) return;
  if (st>t->l->size+1) Print(t->r, st-(t->l->size+1), ed-(t->l->size+1));
  else
    if (st==t->l->size+1)
    {
      fprintf(out, "%c", t->ch);
      Print(t->r, 1, ed-st);
    }
    else
      if (ed<=t->l->size) Print(t->l, st, ed);
      else
        if (ed==t->l->size+1)
        {
          Print(t->l, st, ed-1);
          fprintf(out, "%c", t->ch);
        }
        else
        {
          Print(t->l, st, t->l->size);
          fprintf(out, "%c", t->ch);
          Print(t->r, 1, (ed-st+1)-(t->l->size-st+1)-1);
        }
}

int main()
{
  int lines;
  fscanf(in, "%d\n", &lines);
  nul = (node*) malloc(sizeof(node));
  nul->l=nul->r=nul;
  nul->k=-RAND_MAX;
  nul->ch=0;
  nul->size=0;
  t=nul;
  //initialize
  for (int i=0;i<lines;i++)
  {
    char ch,ch2;
    int num;
    char s1[200];
    ch=fgetc(in);
    ch2=fgetc(in);
    while (ch2!='\n'&&ch2!=' ') ch2=fgetc(in);
    if (ch!='P'&&ch!='N') fscanf(in, "%d", &num);
    if (ch2!='\n') fgetc(in);
    switch (ch)
    {
    case 'M':
      cursor=num+1;
      break;
    case 'I':
      for (int j=0;j<num;j++)
      {
        char ch3;
        ch3=fgetc(in);
        while (ch3=='\n') ch3=fgetc(in);
        t=Insert(t, cursor+j, ch3);
      }
      fgetc(in);
      break;
    case 'D':
      t=Delete(t, cursor, cursor+num-1);
      break;
    case 'G':
      Print(t, cursor, cursor+num-1);
      fprintf(out, "\n");
      break;
    case 'P':
      cursor--;
      break;
    case 'N':
      cursor++;
      break;
    }
  }
}