hdu4699 Editor 2013 多校训练第十场 D题 数列维护 splay | 线段树 | 栈!!!!!

 

题意:维护一个文本编辑,并且查询最大前缀和。

写了splay,wa了13次

过了之后觉着特傻逼。发现题解两个栈就可以了,光标前后维护两个栈,维护前面的栈的前缀和 和 最大前缀和。

哎,傻逼,太弱了,还是没仔细分析题目的特殊性质。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cassert>
#include <iostream>
#include <sstream>
#include <fstream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <algorithm>
#include <iomanip>
using namespace std;

#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))


#define inf 0x3f3f3f3f
#define keyTree (ch[ ch[root][1] ][0])

const int maxn = 2222222;

struct SplayTree {
  int sz[maxn];
  int ch[maxn][2];
  int pre[maxn];
  int root , top1 , top2;
  //int ss[maxn] , que[maxn];

  void Rotate(int x,int f) {
    int y = pre[x];
    ch[y][!f] = ch[x][f];
    pre[ ch[x][f] ] = y;
    pre[x] = pre[y];
    if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
    ch[x][f] = y;
    pre[y] = x;
    push_up(y);
  }
  void Splay(int x,int goal) {
    while(pre[x] != goal) {
      if(pre[pre[x]] == goal) {
        Rotate(x , ch[pre[x]][0] == x);
      } else {
        int y = pre[x] , z = pre[y];
        int f = (ch[z][0] == y);
        if(ch[y][f] == x) {
          Rotate(x , !f) , Rotate(x , f);
        } else {
          Rotate(y , f) , Rotate(x , f);
        }
      }
    }
    push_up(x);
    if(goal == 0) root = x;
  }
  void RotateTo(int k,int goal) {//把第k位的数转到goal下边
    int x = root;
    while(sz[ ch[x][0] ] != k) {
      // printf("x = %d k = %d sz[x] = %d\n",x,k,sz[x]);
      if(k < sz[ ch[x][0] ]) {
        x = ch[x][0];
      } else {
        k -= (sz[ ch[x][0] ] + 1);
        x = ch[x][1];
      }
    }
    Splay(x,goal);
  }


  //以上一般不修改//////////////////////////////////////////////////////////////////////////////
  void debug() {
    printf("%d\n",root);
    Treaval(root);
  }
  void Treaval(int x) {
    if(x) {
      Treaval(ch[x][0]);
      printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
      Treaval(ch[x][1]);
    }
  }
  //以上Debug
  //以下是题目的特定函数:
  void NewNode(int &x,int c) {
    x = ++top1;
    ch[x][0] = ch[x][1] = pre[x] = 0;
    sz[x] = 1;
    val[x] = c;
    sum[x] = c;
    pf[x] = c;
  }
  //把孩子状态更新上来
  void push_up(int x) {
    sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];
    sum[x] = val[x] + sum[ch[x][0]] + sum[ch[x][1]];

    pf[x] = max(pf[ch[x][0]] , sum[ch[x][0]] + val[x] + pf[ch[x][1]] );
    pf[x] = max(pf[x] , sum[ch[x][0]] + val[x]);

    return ;
  }
  /*初始化*/
  void makeTree(int &x,int l,int r,int f) {
    if(l > r) return ;
    int m = (l + r)>>1;
    //  NewNode(x , num[m]);        /*num[m]权值改成题目所需的*/
    makeTree(ch[x][0] , l , m - 1 , x);
    makeTree(ch[x][1] , m + 1 , r , x);
    pre[x] = f;
    push_up(x);
  }
  void clear() {
    cnt = 0 ;
    ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
    val[0] =  sum[0] = 0 ;
    pf[0] = -inf;
    root = top1 = 0;
    //为了方便处理边界,加两个边界顶点
    NewNode(root , -inf);
    NewNode(ch[root][1] , 0);
    pre[top1] = root;
    sz[root] = 2;
  }
  void init(int pos,int n) {
    clear();
    cnt = n;
    RotateTo(pos , 0 );
    RotateTo(pos + 1, root);
    // makeTree(keyTree , 1 , n   , ch[root][1]);
    push_up(ch[root][1]);
    push_up(root);
  }
  void insert(int k , int value) {
    cnt ++ ;
    RotateTo(k - 1 , 0);
    RotateTo(k , root);
    NewNode(keyTree,value);
    pre[keyTree] = ch[root][1];
    push_up(root);
  }
  void del(int k) {
    RotateTo(k - 1 , 0);
    RotateTo(k + 1 , root);
    //printf("val = %d\n",val[keyTree]);
    //printf("sz = %d\n",sz[keyTree]);
    cnt -- ;
    keyTree = 0 ;
    push_up(root);
    // erase(keyTree);
  }
  int query(int k)
  {
    if(k > cnt) k = cnt;
    RotateTo(0,0);
    RotateTo(k + 1 ,root);
    //printf("sz = %d\n",sz[keyTree]);
    return pf[keyTree];
  }
  int cnt ;
  /*这是题目特定变量*/
  int val[maxn];
  int sum[maxn];
  int pf[maxn];
} spt;

int main()
{
  char str[5];
  int Q;
  while(scanf("%d",&Q)!=EOF)
  {
    spt.init(0,0);
    int loc;
    int x;
    loc = 0 ;
    while(Q -- )
    {
      scanf("%s",str);
      if(str[0] == 'I')
      {
        scanf("%d",&x);
        spt.insert(loc + 1 ,x);
        loc ++ ;
      }
      else if(str[0] == 'Q')
      {
        scanf("%d",&x);
        if(x > loc ) x = loc ;
        int ans = spt.query(x);
        printf("%d\n",ans);
      }
      else if(str[0] == 'L')
      {
        if(loc > 0 )
          loc -- ;
      }
      else if(str[0] == 'R')
      {
        if(loc < spt.cnt)
          loc ++ ;
      }
      else if(str[0] == 'D')
      {
        spt.del(loc);
        loc -- ;
      }
     // spt.debug();
    }
  }
  return 0;
}
代码不忍直视

 

以后补上维护栈的代码

posted on 2013-08-22 17:24  oshixiaoxiliu  阅读(466)  评论(3编辑  收藏  举报

导航