大视野1500--splay

来源:互联网 发布:阿卡淘宝商城的旗舰店 编辑:程序博客网 时间:2024/05/05 01:40

Description

Input

输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10
很经典的SPLAY题目。大部分SPLAY需要掌握的操作都有了。
比较麻烦的是max-sum的维护了。联想下线段树区间最大和的维护不难想到splay区间最大和的维护。注意自己本身有一个key。
注意lsum和rsum在reverse操作的时候只要交换一下。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 600080#define inf 0x3f3f3f3f#define Key_value ch[ch[root][1]][0]int X[maxn];inline int max(int a,int b,int c){if(a<b) a = b;if(a<c) a = c;return a;}inline int max(int a,int b,int c,int d,int e,int f){if(a<b) a = b;if(a<c) a = c;if(a<d) a = d;if(a<e) a = e;if(a<f) a = f;return a;}struct SplayTree{int pre[maxn],ch[maxn][2],size[maxn],flip[maxn],root,cnt,cnt1;int set[maxn],sum[maxn],maxsum[maxn],rsum[maxn],lsum[maxn],key[maxn],s[maxn];void Treaval(int x){if(x){PushDown(x);Treaval(ch[x][0]);printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d,key = %2d lsum= %2d  rsum= %2d  maxsum= %2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x],lsum[x],rsum[x],maxsum[x]);Treaval(ch[x][1]);}}void debug(){printf("根节点: %d\n",root);Treaval(root);}void init(int n){cnt = root = cnt1 = 0;ch[0][0] = ch[0][1] = pre[0] = flip[0] = size[0] = sum[0] = 0;maxsum[0] = lsum[0] = rsum[0] = key[0] = -inf;set[0] = inf;NewNode(root,0,-inf);NewNode(ch[root][1],root,-inf);PushUp(root);BuildTree(Key_value,1,n,ch[root][1]);PushUp(ch[root][1]);PushUp(root);}void erase(int r){if(!r)return;s[++cnt1] = r;erase(ch[r][0]);erase(ch[r][1]);}void NewNode(int & r,int father,int num){if(cnt1)r = s[cnt1--];elser = ++cnt;ch[r][0] = ch[r][1] = 0;pre[r] = father;size[r] = 1;flip[r] = 0;sum[r] = maxsum[r] = key[r] = lsum[r] = rsum[r] = num;set[r] = inf;}void PushUp(int x){int l = ch[x][0],r = ch[x][1];size[x] = size[l] + size[r] + 1;sum[x] = sum[l] + sum[r] + key[x];lsum[x] = max(lsum[l],sum[l]+key[x],sum[l]+key[x]+lsum[r]);rsum[x] = max(rsum[r],key[x]+sum[r],rsum[l]+key[x]+sum[r]);maxsum[x] = max(maxsum[l],maxsum[r],rsum[l]+key[x],key[x],lsum[r]+key[x],rsum[l]+lsum[r]+key[x]);}void BuildTree(int & r,int L,int R,int father){if(L > R) return;int mid = (L + R) >> 1;NewNode(r,father,X[mid]);BuildTree(ch[r][0],L,mid-1,r);BuildTree(ch[r][1],mid+1,R,r);PushUp(r);}void Update_Rev(int x){if(!x)return;swap(ch[x][0],ch[x][1]);swap(lsum[x],rsum[x]);flip[x] ^= 1;}void Update_Set(int x,int a){if(!x)return;flip[x] = 0;key[x] = a;set[x] = a;sum[x] = size[x]*a;if(a>0)maxsum[x] = lsum[x] = rsum[x] = sum[x];else maxsum[x] = lsum[x] = rsum[x] = a;}void PushDown(int x){if(flip[x]){Update_Rev(ch[x][0]);Update_Rev(ch[x][1]);flip[x] = 0;}if(set[x]!=inf){Update_Set(ch[x][0],set[x]);Update_Set(ch[x][1],set[x]);set[x] = inf;}}void Rotate(int x,int kind){int y = pre[x];PushDown(y);PushDown(x);ch[y][!kind] = ch[x][kind];pre[ch[x][kind]] = y;if(pre[y])ch[pre[y]][ch[pre[y]][1]==y] = x;pre[x] = pre[y];ch[x][kind] = y;pre[y] = x;PushUp(y);}void Splay(int r,int goal){PushDown(r);while(pre[r] != goal){int y = pre[r],z = pre[y];//PushDown(z);PushDown(y);PushDown(r);if(z == goal)Rotate(r,ch[y][0] == r);else {int kind = (ch[z][0] == y);if(ch[y][kind] == r){Rotate(r,!kind);Rotate(r,kind);}else {Rotate(y,kind);Rotate(r,kind);}}}PushUp(r);if(goal == 0)root = r;}int Get_Kth(int r,int k){int o = r;while(o){PushDown(o);int t = size[ch[o][0]] + 1;if(t == k)return o;else if(t > k){o = ch[o][0];}else {k -= t;o = ch[o][1];}}}int Get_Min(int r){PushDown(r);while(ch[r][0]){r = ch[r][0];PushDown(r);}return r;}int Get_Max(int r){PushDown(r);while(ch[r][1]){r = ch[r][1];PushDown(r);}return r;}void insert(int k,int tot){int x = Get_Kth(root,k+1);Splay(x,0);int y = Get_Min(ch[root][1]);Splay(y,root);BuildTree(Key_value,1,tot,ch[root][1]);;PushUp(ch[root][1]);PushUp(root);Splay(Key_value,0);}void remove(int k,int tot){int x = Get_Kth(root,k);Splay(x,0);int y = Get_Kth(root,k+tot+1);Splay(y,root);erase(Key_value);pre[Key_value] = 0;Key_value = 0;PushUp(ch[root][1]);PushUp(root);}void Set(int k,int tot,int a){int x = Get_Kth(root,k);Splay(x,0);int y = Get_Kth(root,k+tot+1);Splay(y,root);Update_Set(Key_value,a);PushUp(ch[root][1]);PushUp(root);Splay(Key_value,0);}void Reversal(int l,int tot){int x = Get_Kth(root,l);Splay(x,0);int y = Get_Kth(root,l+tot+1);Splay(y,root);Update_Rev(Key_value);PushUp(ch[root][1]);PushUp(root);Splay(Key_value,0);}int Querysum(int k,int tot){int x = Get_Kth(root,k);Splay(x,0);int y = Get_Kth(root,k+tot+1);Splay(y,root);return sum[Key_value];}int Querymaxsum(){        int x = Get_Kth(root,1);         Splay(x,0);         int y = Get_Max(root);         Splay(y,root);         return maxsum[Key_value]; }void solve(int n,int m){for(int i = 1;i <= n;i++)scanf("%d",&X[i]);init(n);while(m--){char ope[10];scanf("%s",ope);if(ope[0] == 'G'){int pos,tot;scanf("%d%d",&pos,&tot);printf("%d\n",Querysum(pos,tot));}else if(ope[0] == 'I'){int pos,tot;scanf("%d%d",&pos,&tot);for(int i = 1;i <= tot;i++)scanf("%d",&X[i]);insert(pos,tot);}else if(ope[0] == 'D'){int pos,tot;scanf("%d%d",&pos,&tot);remove(pos,tot);}else if(ope[0] == 'R'){int pos,tot;scanf("%d%d",&pos,&tot);Reversal(pos,tot);}else if(ope[0] == 'M' && ope[2] == 'X'){printf("%d\n",Querymaxsum());}else{int pos,tot,c;scanf("%d%d%d",&pos,&tot,&c);Set(pos,tot,c);}}}}spt;int main(){//freopen("in.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)==2){spt.solve(n,m);}}


0 0