曬一曬咱splay的醜代碼;



             發現單旋splay簡單易懂,清晰明瞭,容易調試(?,貌似標記不弄錯就不會出錯),所以以後平衡樹都寫它算了。

             貼代碼,萬一以後找不到了=。=!

             沒有什麼好註釋的。

              1,需要注意的是這裏splay(i,k)的含義是指通過splay操作時的i位置的左子樹的節點爲k;

              2,一定要注意標記的下方和使用,以及0節點的情況。

              3,一開始加了一個極左點和極後點,防止splay樹爲空,操作時需要注意;

              4,樹形態改變後及時updata,否則死都不知道死哪裏了。

              5,單旋splay可以適當隨機提根。

             noi2005 sequence :

 

# include <cstdlib>
# include <cmath>
# include <cstdio>

using namespace std;
 
const int oo = 107374189, maxn = 4000000+100;
int a[maxn], same[maxn],size[maxn], sum[maxn], maxl[maxn], maxr[maxn], maxs[maxn], link[maxn][2];
bool need[maxn], spin[maxn];
int m, n, root, pos, tot;
char c1, c2, c3;

inline void swap(int &x, int &y) {int tmp = x; x = y; y = tmp;};
inline int max(int x, int y) {return x > y? x: y;};

void updata(int i)
{
   size[i]= size[link[i][0]] + size[link[i][1]] + 1;
   sum[i] = sum[link[i][0]] + sum[link[i][1]] + a[i];
   maxl[i] = max( maxl[link[i][0]], sum[link[i][0]] + maxl[link[i][1]] + a[i]);
   maxr[i] = max( maxr[link[i][1]], sum[link[i][1]] + maxr[link[i][0]] + a[i]);
   maxs[i] = max( max( maxs[link[i][0]], maxs[link[i][1]]), maxr[link[i][0]] + maxl[link[i][1]] + a[i]);  
}

void release(int i)
{
  if (i == 0) return;
  a[i] = same[i], sum[i] = a[i]*size[i];
  maxl[i] = maxr[i] = max(0, size[i]*a[i]);
  maxs[i] = max(a[i], size[i]*a[i]);
  need[i] = 1;
}

void handle(int i)
{
	if (i == 0) return;
	spin[i] ^= 1;
	swap(maxl[i], maxr[i]);
}

void pushdown(int i)
{
  if (need[i] != 0) 
     same[link[i][0]] = same[link[i][1]] = a[i] = same[i], same[i] = 0, need[i] = false,
	 spin[i] = 0, need[link[i][0]] = 1, need[link[i][1]] = 1, release(link[i][0]), release(link[i][1]), updata(i);
  if (spin[i] != 0) 
	 handle(link[i][0]), handle(link[i][1]), spin[i] = 0, swap(link[i][0], link[i][1]), updata(i); 
}

void dfs(int i)
{
  if (i == 0) return;
  //if (need[i]) return;
  int dl, dr, ds, dz;
  dl=maxl[i];
  dr=maxr[i];
  ds=maxs[i], dz= size[i];
  pushdown(i);
  dfs(link[i][0]); dfs(link[i][1]);
  updata(i);
  i = i;
}

int build(int l, int r)
{
   int mid = l+r>> 1;
   if (l < mid) link[mid][0] = build(l, mid-1);
   if (mid < r) link[mid][1] = build(mid+1, r);
   updata(mid);
   return mid; 
}

void read()
{
   freopen("sequence.in", "r", stdin);
   freopen("sequence.out", "w", stdout);
   int i;
   scanf("%d%d", &n, &m); n+= 2; a[1] = -oo; a[n] = -oo; maxs[0] = -oo;
   for (i = 1; i < n; i++) scanf("%d", &a[i+1]);
   root = build(1, n);
}

void rotate(int &i, int p)
{
  int j = link[i][p];
  link[i][p] = link[j][!p];
  link[j][!p] = i;
  updata(i);updata(j);i = j; 
}

void splay(int &i, int k)
{
  pushdown(i);
  int s = size[link[i][0]];
  if (s < k) splay(link[i][1], k-s-1), rotate(i,1);
  else if (s > k)splay(link[i][0], k), rotate(i,0);
}

inline void leave(int l, int r)
{
  splay(root, r); 
  splay(link[root][0], l-2); updata(root);
}

void Insert()
{
  int i;
   for (i = 1; i <= 3; i++) scanf("%c", &c3);
   scanf("%d%d", &pos, &tot); pos++;
   for (i = 1; i <= tot; i++) scanf("%d", &a[n+i]); scanf("\n");
   leave(pos+1, pos); 
   link[link[root][0]][1] = build(n+1, n+tot); 
   updata(link[root][0]); updata(root);
   n+= tot; 
}

void Delete()
{
  int i;
   for (i = 1; i <= 3; i++) scanf("%c", &c3);
   scanf("%d%d\n", &pos, &tot);pos++;
   leave(pos, pos+tot-1);
   link[link[root][0]][1] = 0; updata(link[root][0]); updata(root);
 //  n -= tot;
}

void Makesame() 
{
  int i, c;
   for (i = 1; i <= 6; i++) scanf("%c", &c3);
   scanf("%d%d%d\n", &pos, &tot, &c); pos++;
   leave(pos, pos+tot-1);
   int d = link[link[root][0]][1]; need[d] = 1;
   same[d] = c; release(d); updata(link[root][0]); updata(root);
}

void Reverse()
{
  int i;
   for (i = 1; i <= 4; i++) scanf("%c", &c3);
   scanf("%d%d\n", &pos, &tot);pos++;
   leave(pos, pos+tot-1);
   int d = link[link[root][0]][1]; 
   spin[d] ^= 1; swap(maxl[d], maxr[d]); 
   updata(link[root][0]); updata(root);
}

void Getsum()
{
  int i;  //dfs(root);
   for (i = 1; i <= 4; i++) scanf("%c", &c3);
   scanf("%d%d\n", &pos, &tot); pos++;
   leave(pos, pos+tot-1);
   printf("%d\n", sum[link[link[root][0]][1]]);
}

void Maxsum()
{
  int i; 
  //dfs(root);
  for (i = 1; i <= 4; i++) scanf("%c", &c3); scanf("\n");
  printf("%d\n", maxs[root]);
}


int main()
{
   read(); int i;
   for (i = 1; i <= m; i++)
   {
     //dfs(root);
     scanf("%c%c%c", &c1, &c2, &c3);
     if (c1 == 'I') Insert();
     else if (c1 == 'D') Delete();
     else if (c1 == 'M' && c2 == 'A' && c3 == 'K') Makesame();
     else if (c1 == 'R') Reverse();
     else if (c1 == 'G') Getsum();
     else if (c1 == 'M' && c2 == 'A' && c3 == 'X') Maxsum();
   }
   return 0;
}

hnoi2011 brackets:

# include <cstdlib>
# include <cstdio>
# include <cmath>

using namespace std;

const int maxn = 200000;
int sum[maxn], size[maxn], a[maxn], maxl[maxn], maxr[maxn], minl[maxn], minr[maxn], link[maxn][2], same[maxn];
bool spin[maxn], rev[maxn];
int i, n, m, root;
char tmp[10];

inline int max(int x, int y) {return x > y? x: y;};
inline int min(int x, int y) {return x < y? x: y;};
inline void swap(int &x, int &y) {int tmp = x; x = y; y = tmp;};
inline int abs(int x) {return x < 0? -x:x;};

void updata(int i)
{
  size[i] = size[link[i][0]] + size[link[i][1]] + 1;
  sum[i] = sum[link[i][0]] + a[i] + sum[link[i][1]];
  maxl[i] = max(maxl[link[i][0]], sum[link[i][0]] + a[i] + maxl[link[i][1]]);
  minl[i] = min(minl[link[i][0]], sum[link[i][0]] + a[i] + minl[link[i][1]]);
  maxr[i] = max(maxr[link[i][1]], sum[link[i][1]] + a[i] + maxr[link[i][0]]);
  minr[i] = min(minr[link[i][1]], sum[link[i][1]] + a[i] + minr[link[i][0]]);
}

int build(int l, int r)
{
  int mid = l+r>>1;
  if (l < mid) link[mid][0] = build(l, mid-1);
  if (mid < r) link[mid][1] = build(mid+1, r);
  updata(mid);
  return mid;
}

void read()
{
  freopen("brackets.in", "r", stdin);
  freopen("brackets.out", "w", stdout);
  scanf("%d%d\n", &n, &m); n+=2;
  int i; char c;
  for (i = 2; i < n; i++) 
  {
    scanf("%c", &c);
    a[i]= c== '(' ? 1:-1;
  }
  root = build(1,n);
  scanf("\n");
}

void rotate(int &i, int p)
{
  int j = link[i][p];
  link[i][p] = link[j][!p];
  link[j][!p] = i;
  updata(i); updata(j); i = j;
}

void hsame(int i, int d)
{
  if (!i) return;
  same[i]=d; rev[i] = 0; spin[i] = 0;
  sum[i] = size[i]*d; a[i]=d;
  maxr[i]=maxl[i] = max(0, sum[i]); 
  minr[i]=minl[i] = min(0, sum[i]);
}

void hspin(int i)
{
  if (!i) return;
  spin[i]^= 1;
  swap(link[i][0], link[i][1]);
  swap(maxl[i], maxr[i]); swap(minl[i], minr[i]);
}

void hrev(int i)
{
  if (!i) return;
  rev[i]^= 1;
  swap(maxl[i],minl[i]); swap(maxr[i],minr[i]);
  maxl[i] = -maxl[i], maxr[i]= -maxr[i], minl[i] = -minl[i], minr[i] = -minr[i];
  sum[i] = 0-sum[i]; a[i] = -a[i];
} 

void pushdown(int i)
{
  if (same[i] != 0)
    hsame(link[i][0], same[i]), hsame(link[i][1], same[i]),
    same[i] = 0;  
  if (rev[i] != 0)
    hrev(link[i][0]), hrev(link[i][1]),
    rev[i] = 0;
  if (spin[i] != 0)
    hspin(link[i][0]), hspin(link[i][1]),
    spin[i] = 0;
}

void splay(int &i, int k)
{
  pushdown(i);
  int s = size[link[i][0]];
  if (s > k) splay(link[i][0], k), rotate(i,0);
  else if (s< k) splay(link[i][1], k-s-1), rotate(i,1);
  updata(i);
}

void leave(int l, int r)
{
  splay(root, r);
  splay(link[root][0], l-2); updata(root);
}

void replace()
{
  int l, r; char c;
  scanf("%d%d ", &l, &r); scanf("%c\n", &c);
  leave(++l, ++r); 
  hsame(link[link[root][0]][1], (c=='(')*2-1);
  updata(link[root][0]); updata(root);
}

void swap()
{
  int l, r;
  scanf("%d%d\n", &l, &r);
  leave(++l, ++r);
  hspin(link[link[root][0]][1]);
  updata(link[root][0]); updata(root);
}

void invert()
{
  int l, r;
  scanf("%d%d\n", &l, &r);
  leave(++l, ++r);
  hrev(link[link[root][0]][1]);
  updata(link[root][0]); updata(root);
}

void dfs(int i)
{
   if (!i) return;
   pushdown(i);
   dfs(link[i][0]); dfs(link[i][1]);
   updata(i);
}

void query()
{
  int l, r, u, v;
  scanf("%d%d\n", &l, &r);
  leave(++l, ++r);
  //dfs(root);
  int d= link[link[root][0]][1];
  u = abs(minl[d]), v = abs(maxr[d]);
  if (u & 1) printf("%d\n", u/2+v/2+2);
  else printf("%d\n", (u+v)/2);
 }

int main()
{
   read(); 
   for (i = 1; i <= m; i++)
   {
     scanf("%s", tmp);
     if (tmp[0] == 'R') replace();
     else if (tmp[0] == 'S') swap();
     else if (tmp[0] == 'I') invert();
     else query();
   }
   return 0;
}

poj 3580 supermemo:

# include <cstdlib>
# include <cstdio>
# include <cmath>
# include <ctime>

using namespace std;

const int oo = 1073741819, maxn = 300000+5;
int  spin[maxn],a[maxn], link[maxn][2], sum[maxn], size[maxn], bj[maxn];
int n, m, root;

inline int min(int x, int y) {return x < y?x:y;}
inline void swap(int &x, int &y) {int tmp = x; x = y; y = tmp;}


inline void updata(int x)
{
  sum[x] = min(a[x], min(sum[link[x][0]], sum[link[x][1]]));
  size[x] = size[link[x][1]]+ 1 +size[link[x][0]];
}


int build(int l, int r)
{
  int mid = l+r>>1;
  if (l<mid) link[mid][0] = build(l, mid-1);
  if (mid<r) link[mid][1] = build(mid+1, r);
  updata(mid);
  return mid;
}


void read()
{
  freopen("3580.in", "r", stdin);
  freopen("3580.out", "w", stdout);
  scanf("%d", &n); n+= 2; a[0] = a[n] = sum[0] = sum[n] = oo;
  for (int i = 2; i < n; i++) scanf("%d", &a[i]);
  root = build(1, n);
}

void rotate(int &i, int p)
{
  int j = link[i][p];
  link[i][p] = link[j][!p];
  link[j][!p] = i;
  updata(i); updata(j); i=j;
}

inline void hbj(int i, int d)
{
  if (!i) return;
  bj[i] += d; sum[i]+= d; a[i] += d;
}

inline void hspin(int i)
{
  if (!i) return;
  spin[i]^=1; swap(link[i][0], link[i][1]);
}

inline void pushdown(int i)
{
  if (!i) return;
  if (spin[i]) 
    hspin(link[i][0]), hspin(link[i][1]), spin[i] = 0;
  if (bj[i] != 0)
    hbj(link[i][0],bj[i]), hbj(link[i][1],bj[i]),bj[i]=0;
}

void splay(int &i, int k)
{
  int s = size[link[i][0]];
  pushdown(i);
  if (s > k) splay(link[i][0], k), rotate(i, 0);
  else if (s < k) splay(link[i][1], k-s-1), rotate(i, 1);
  updata(i);
}

void leave(int l, int r)
{
  splay(root, r); 
  splay(link[root][0], l-2);
  updata(root);
}

void dfs(int i)
{
	if (!i) return;
	pushdown(i);
	dfs(link[i][0]); dfs(link[i][1]);
	updata(i);
}

int main()
{
  srand(int(time (NULL)));
  int have;
  read(); int l,r,d,mid,x; char tmp[10]; have=n; 
  scanf("%d\n", &m); 
  for (int i = 1; i <= m; i++)
  {
    scanf("%s", tmp+1);
    //dfs(root);
    if (tmp[1]=='A') 
    {
      scanf("%d%d%d\n", &l, &r, &d);
      leave(++l, ++r); int c = link[link[root][0]][1]; 
      hbj(c, d);updata(link[root][0]); updata(root);
    }
    else if (tmp[1]=='R'&&tmp[6]=='S') 
    {
      scanf("%d%d\n", &l, &r);
      leave(++l,++r);  int c = link[link[root][0]][1];
      hspin(c); updata(link[root][0]); updata(root);
    }
    else if (tmp[1]=='R'&&tmp[6]=='V')
    {
      scanf("%d%d%d\n", &l, &r, &d); ++l;++r;d %= r-l+1; mid=r-d;
      if (!d) continue;
      splay(root,mid-1), splay(link[root][0], l-2), splay(link[root][1], r-mid);
      int u = link[root][0], v = link[root][1], tmp;
      //tmp = link[v][0]; link[v][0] = link[u][1]; link[u][1] = 0;link[root][0] = tmp;
	  link[root][0] = link[u][1]; link[u][1] = link[v][0]; link[v][0] = 0;  
      updata(u); updata(v); updata(root);
      splay(root,0); link[root][0] = u; updata(root); 
    }
    else if (tmp[1]=='I') 
    {
      scanf("%d%d\n", &x, &a[++n]);++x;
      leave(x+1,x); int c = link[root][0];
      link[c][1] = n; updata(n); updata(c); updata(root); ++have;
    }
    else if (tmp[1]=='D')
    {
      scanf("%d\n", &x);++x;
      leave(x,x); int c = link[root][0];
      link[c][1] = 0; updata(c); updata(root);--have;
    }
    else 
    {
      scanf("%d%d\n", &l, &r);
      leave(++l,++r); int c = link[link[root][0]][1];
      //dfs(root);
      printf("%d\n", sum[c]);
    }
    //splay(root, ((rand()<<15)+rand())%have); 
    //splay(root, ((rand()<<15)+rand())%have);
  }
  
  return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章