题意:维护一个文本编辑,并且查询最大前缀和。
写了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 ",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 ",root); Treaval(root); } void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d ",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 ",val[keyTree]); //printf("sz = %d ",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 ",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 ",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; }
以后补上维护栈的代码