输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
splay激情应用
修改和翻转操作懒惰标记就不多说
对于MAX操作,每个节点维护l,r,MAX分别代表这个节点控制的区间中,从左开始加能加的最大值,从右开始能加的最大值,这个区间的最大子序列,splay能支持线段树上的操作~
插入时根据splay插入定义,将待插入区间转换为序列,通过一次split和两次merge完成,苟蒻的第一版代码一个个点插入(理论上可行)不过要每次插入把新节点转到根,这样插入一个序列必形成一条链,常数吃不消(最后以10s时间A了...),第二版改进插入,变为插入一棵完全二叉树,二分实现,时间几乎缩短为一半
写的时候下标出了点差错,maintain维护不到位等
第一版激情9kb
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> using namespace std; const int maxn = 5E5 + 50; const int p = 1001; int n,m; class data { private: struct Node { Node *ch[2]; int siz,rev,modi,l,r,MAX,num,sum,po; }*root,pool[maxn]; int bo[maxn],now; void maintain(Node *&x) { int s1,s2,sl,sr,suml,sumr; x->MAX = -2E9; x->sum = x->num; x->l = x->r = 0; s1 = s2 = sl = sr = suml = sumr = 0; if (x->ch[0] != NULL) { s1 = x->ch[0]->siz; sl = x->ch[0]->r; suml = x->ch[0]->sum; x->MAX = max(x->ch[0]->MAX,x->MAX); x->sum += x->ch[0]->sum; x->l = max(x->l,x->ch[0]->l); } if (x->ch[1] != NULL) { s2 = x->ch[1]->siz; sr = x->ch[1]->l; sumr = x->ch[1]->sum; x->MAX = max(x->ch[1]->MAX,x->MAX); x->sum += x->ch[1]->sum; x->r = max(x->r,x->ch[1]->r); } x->MAX = max(x->MAX,sl + sr + x->num); x->siz = s1 + s2 + 1; x->l = max(x->l,suml + x->num + sr); x->r = max(x->r,sumr + x->num + sl); } void pushdown(Node *&x) { if (x->rev) { swap(x->ch[0],x->ch[1]); for (int i = 0; i < 2; i++) if (x->ch[i] != NULL) x->ch[i]->rev ^= 1,swap(x->ch[i]->l,x->ch[i]->r); x->rev ^= 1; } if (x->modi < p) { for (int i = 0; i < 2; i++) if (x->ch[i] != NULL) { int t = x->modi; x->ch[i]->num = x->ch[i]->modi = t; x->ch[i]->sum = t*x->ch[i]->siz; if (t > 0) x->ch[i]->l = x->ch[i]->r = x->ch[i]->MAX = x->ch[i]->sum; else x->ch[i]->l = x->ch[i]->r = 0,x->ch[i]->MAX = t; } x->modi = p; } maintain(x); } void rotate(Node *&x,int d) { Node *y = x->ch[d]; x->ch[d] = y->ch[d^1]; y->ch[d^1] = x; maintain(x); x = y; maintain(x); } void splay(Node *&x,int rank) { pushdown(x); int s1 = x->ch[0] == NULL?0:x->ch[0]->siz; if (s1 + 1 == rank) return; int d; if (s1 + 1 < rank) { rank = rank - s1 - 1; d = 1; } else d = 0; pushdown(x->ch[d]); int s2 = x->ch[d]->ch[0] == NULL?0:x->ch[d]->ch[0]->siz; if (s2 + 1 != rank) { int d1; if (s2 + 1 < rank) d1 = 1,rank = rank - s2 - 1; else d1 = 0; pushdown(x->ch[d]->ch[d1]); splay(x->ch[d]->ch[d1],rank); if (d == d1) rotate(x,d); else rotate(x->ch[d],d1); } rotate(x,d); } Node *merge(Node *left,Node *right) { splay(left,left->siz); left->ch[1] = right; maintain(left); return left; } void split(Node *x,Node *&left,Node *&right,int rank) { splay(x,rank); right = x->ch[1]; x->ch[1] = NULL; left = x; maintain(left); } void DEL(Node *&x) { if (x->ch[0] != NULL) DEL(x->ch[0]); if (x->ch[1] != NULL) DEL(x->ch[1]); x->ch[0] = x->ch[1] = NULL; bo[++now] = x->po; } public: data() { root = &pool[0]; root->num = 0; root->rev = 0; root->modi = p; maintain(root); for (int i = 1; i <= 500000; i++) bo[i] = i; now = 500000; } void Insert (int rank,int num) { Node *left,*right; split(root,left,right,rank); left->ch[1] = &pool[bo[now]]; Node *&x = left->ch[1]; x->po = bo[now--]; x->num = num; x->rev = 0; x->modi = p; maintain(x); maintain(left); root = merge(left,right); splay(root,rank+1); } void Remove(int pos,int tot) { splay(root,pos); if (pos + tot == n) { DEL(root->ch[1]); root->ch[1] = NULL; maintain(root); } else { splay(root->ch[1],tot+1); DEL(root->ch[1]->ch[0]); root->ch[1]->ch[0] = NULL; maintain(root->ch[1]); maintain(root); } } void Modify(int pos,int tot,int num) { splay(root,pos); Node *x; if (pos + tot == n) x = root->ch[1]; else { splay(root->ch[1],tot+1); x = root->ch[1]->ch[0]; } x->modi = x->num = num; int t = x->modi; x->sum = t*x->siz; if (t > 0) x->l = x->r = x->MAX = x->sum; else x->l = x->r = 0,x->MAX = t; if (pos + tot == n) root->ch[1] = x; else root->ch[1]->ch[0] = x; if (pos + tot != n) maintain(root->ch[1]); maintain(root); } void Rever(int pos,int tot) { splay(root,pos); Node *x; if (pos + tot == n) x = root->ch[1]; else { splay(root->ch[1],tot+1); x = root->ch[1]->ch[0]; } x->rev ^= 1; swap(x->l,x->r); if (pos + tot == n) root->ch[1] = x; else root->ch[1]->ch[0] = x; if (pos + tot != n) maintain(root->ch[1]); maintain(root); } int SUM(int pos,int tot) { splay(root,pos); if (pos + tot == n) return root->ch[1]->sum; else { splay(root->ch[1],tot+1); return root->ch[1]->ch[0]->sum; } } int MAXSUM() { splay(root,1); return root->ch[1]->MAX; } }; char co[10]; int getcom() { scanf("%s",co); if (co[0] == 'I') return 1; if (co[0] == 'D') return 2; if (co[0] == 'R') return 4; if (co[0] == 'G') return 5; int len = strlen(co); if (len > 7) return 3; else return 6; } int typ,tot,pos; int main() { #ifdef YZY freopen("yzy.txt","r",stdin); #endif scanf("%d%d",&n,&m); static data tree; int N = n; n = 1; for (int i = 1; i <= N; i++) { int x; scanf("%d",&x); ++n; tree.Insert(i,x); } while (m--) { typ = getcom(); if (typ == 1) { int c; scanf("%d%d",&pos,&tot); if (!tot) continue; for (int i = pos + 1; i <= pos + tot; i++) { scanf("%d",&c); ++n; tree.Insert(i,c); } } else if (typ == 2) { scanf("%d%d",&pos,&tot); if (!tot) continue; tree.Remove(pos,tot); n -= tot; } else if (typ == 3) { int c; scanf("%d%d%d",&pos,&tot,&c); if (!tot) continue; tree.Modify(pos,tot,c); } else if (typ == 4) { scanf("%d%d",&pos,&tot); if (!tot) continue; tree.Rever(pos,tot); } else if (typ == 5) { scanf("%d%d",&pos,&tot); if (!n || !tot) printf("0\n"); else printf("%d\n",tree.SUM(pos,tot)); } else { if (!n) printf("0\n"); else printf("%d\n",tree.MAXSUM()); } } return 0; }
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> using namespace std; const int maxn = 5E5 + 50; const int p = 1001; struct Node{ Node *ch[2]; int num,siz,sum,MAX,l,r,rev,modi,po; }*root,pool[maxn]; int n,m,cnt,a[maxn],bo[maxn]; int cmp(Node *x,int &rank) { int s0 = x->ch[0] == NULL?0:x->ch[0]->siz; if (s0+1 == rank) return -1; if (s0+1 < rank) { rank = rank-s0-1; return 1; } return 0; } void maintain(Node *&x) { x->siz = 1; x->sum = x->num; x->l = x->r = 0; x->MAX = x->num; int s0,s1,sl,sr; s0 = s1 = sl = sr = 0; if (x->ch[0] != NULL) { x->siz += x->ch[0]->siz; x->sum += x->ch[0]->sum; s0 = x->ch[0]->sum; x->MAX = max(x->MAX,x->ch[0]->MAX); sl = x->ch[0]->r; x->l = max(x->l,x->ch[0]->l); } if (x->ch[1] != NULL) { x->siz += x->ch[1]->siz; x->sum += x->ch[1]->sum; s1 = x->ch[1]->sum; x->MAX = max(x->MAX,x->ch[1]->MAX); sr = x->ch[1]->l; x->r = max(x->r,x->ch[1]->r); } x->MAX = max(x->MAX,sl+sr+x->num); x->l = max(x->l,s0+x->num+sr); x->r = max(x->r,s1+x->num+sl); } void pushdown(Node *&x) { for (int i = 0; i < 2; i++) if (x->ch[i] != NULL) { if (x->rev) { x->ch[i]->rev ^= 1; swap(x->ch[i]->ch[0],x->ch[i]->ch[1]); swap(x->ch[i]->l,x->ch[i]->r); } if (x->modi != p) { x->ch[i]->num = x->ch[i]->modi = x->modi; x->ch[i]->sum = x->modi*x->ch[i]->siz; if (x->modi > 0) x->ch[i]->l = x->ch[i]->r = x->ch[i]->MAX = x->ch[i]->sum; else x->ch[i]->l = x->ch[i]->r = 0,x->ch[i]->MAX = x->modi; } } x->rev = 0; x->modi = p; } void rotate(Node *&x,int d) { Node *y = x->ch[d]; x->ch[d] = y->ch[d^1]; y->ch[d^1] = x; maintain(x); x = y; maintain(x); } void splay(Node *&x,int rank) { pushdown(x); int d1 = cmp(x,rank); if (d1 == -1) return; pushdown(x->ch[d1]); int d2 = cmp(x->ch[d1],rank); if (d2 != -1) { pushdown(x->ch[d1]->ch[d2]); splay(x->ch[d1]->ch[d2],rank); if (d1 == d2) rotate(x,d1); else rotate(x->ch[d1],d2); } rotate(x,d1); } void Insert(Node *&x,int l,int r) { if (l > r) return; x = &pool[bo[cnt]]; x->modi = p; x->rev = 0; x->ch[0] = x->ch[1] = NULL; x->po = bo[cnt--]; int mid = (l+r) >> 1; x->num = a[mid]; Insert(x->ch[0],l,mid-1),Insert(x->ch[1],mid+1,r); maintain(x); } void Delete(Node *&x) { for (int i = 0; i < 2; i++) if (x->ch[i] != NULL) Delete(x->ch[i]); bo[++cnt] = x->po; x = NULL; } Node *merge(Node *left,Node *right) { splay(left,left->siz); left->ch[1] = right; maintain(left); return left; } void split(Node *&left,Node *&right,int rank) { splay(root,rank); right = root->ch[1]; left = root; left->ch[1] = NULL; maintain(left); } char ch[10]; int getcom() { scanf("%s",&ch); if (ch[0] == 'I') return 1; if (ch[0] == 'D') return 2; if (ch[0] == 'R') return 4; if (ch[0] == 'G') return 5; int len = strlen(ch); if (len <= 7) return 6; return 3; } int main() { #ifdef YZY freopen("sequence2.in","r",stdin); #endif cin >> n >> m; root = &pool[0]; root->rev = 0; root->modi = p; root->num = 0; maintain(root); for (cnt = 1; cnt <= 500000; cnt++) bo[cnt] = cnt; --cnt; for (int i = 1; i <= n; i++) scanf("%d",&a[i]); Insert(root->ch[1],1,n); ++n; maintain(root); while (m--) { int com = getcom(); if (com == 6) { splay(root,1); if (n == 1) { if (com == 5) printf("0\n"); continue; } printf("%d\n",root->ch[1]->MAX); } else { int pos,tot; scanf("%d%d",&pos,&tot); if (!tot) { if (com == 5) printf("0\n"); continue; } Node *left,*right; if (com == 1) { for (int i = pos+1; i <= pos+tot; i++) scanf("%d",&a[i]); split(left,right,pos+1); Insert(left->ch[1],pos+1,pos+tot); maintain(left); root = merge(left,right); n += tot; } else if (com == 2) { splay(root,pos); if (pos + tot == n) { Delete(root->ch[1]); maintain(root); } else { splay(root->ch[1],tot+1); Delete(root->ch[1]->ch[0]); maintain(root->ch[1]); maintain(root); } n -= tot; } else if (com == 3) { int c; scanf("%d",&c); splay(root,pos); Node *x; if (pos + tot == n) x = root->ch[1]; else splay(root->ch[1],tot+1),x = root->ch[1]->ch[0]; x->num = x->modi = c; x->sum = c*x->siz; if (c > 0) x->l = x->r = x->MAX = x->sum; else x->l = x->r = 0,x->MAX = c; if (pos + tot != n) { root->ch[1]->ch[0] = x; maintain(root->ch[1]); } else root->ch[1] = x; maintain(root); } else if (com == 4) { splay(root,pos); Node *x; if (pos + tot == n) x = root->ch[1]; else splay(root->ch[1],tot+1),x = root->ch[1]->ch[0]; x->rev ^= 1; swap(x->ch[0],x->ch[1]); swap(x->l,x->r); if (pos + tot != n) { root->ch[1]->ch[0] = x; maintain(root->ch[1]); } else root->ch[1] = x; maintain(root); } else { splay(root,pos); if (pos + tot == n) printf("%d\n",root->ch[1]->sum); else { splay(root->ch[1],tot+1); printf("%d\n",root->ch[1]->ch[0]->sum); } } } } return 0; }
狗日的第三代。。。又调了老半天
首先。。split写了一开始居然没有用
然后。。maintain里面l,r初值应赋0,MAX初值为当前点的数
恩。。NEW函数一开始没有返回值
没特判tot等于0的情形
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn = 5E5 + 50; const int INF = ~0U>>1; struct Node{ int l,r,num,MAX,modi,rev,po,siz,sum; Node *ch[2]; }pool[maxn],*root; int n,m,cnt,pos,tot,sta[maxn],a[maxn]; char cha[10]; void maintain(Node *&x) { int s,sl,sr,s0,s1; s = sl = sr = s0 = s1 = 0; x->l = x->r = 0; x->MAX = x->num; if (x->ch[0] != NULL) { x->MAX = max(x->MAX,x->ch[0]->MAX); s += x->ch[0]->siz; sl = x->ch[0]->sum; s0 = x->ch[0]->r; x->l = x->ch[0]->l; } if (x->ch[1] != NULL) { x->MAX = max(x->MAX,x->ch[1]->MAX); s += x->ch[1]->siz; sr = x->ch[1]->sum; s1 = x->ch[1]->l; x->r = x->ch[1]->r; } x->sum = sl + sr + x->num; x->siz = s + 1; x->MAX = max(x->MAX,s0 + s1 + x->num); x->l = max(x->l,sl + x->num + s1); x->r = max(x->r,sr + x->num + s0); } void rotate(Node *&x,int d) { Node *y = x->ch[d]; x->ch[d] = y->ch[d^1]; y->ch[d^1] = x; maintain(x); x = y; maintain(x); } void pushdown(Node *&x) { if (x->rev) { for (int i = 0; i < 2; i++) if (x->ch[i] != NULL) { swap(x->ch[i]->ch[0],x->ch[i]->ch[1]); swap(x->ch[i]->l,x->ch[i]->r); x->ch[i]->rev ^= 1; } x->rev ^= 1; } if (x->modi != INF) { int b = x->modi; for (int i = 0; i < 2; i++) if (x->ch[i] != NULL) { x->ch[i]->num = x->ch[i]->modi = b; x->ch[i]->sum = b*x->ch[i]->siz; if (b > 0) x->ch[i]->l = x->ch[i]->r = x->ch[i]->MAX = x->ch[i]->sum; else x->ch[i]->l = x->ch[i]->r = 0,x->ch[i]->MAX = b; } x->modi = INF; } maintain(x); } int Judge(Node *x,int &rank) { int s = x->ch[0] == NULL?0:x->ch[0]->siz; ++s; if (s == rank) return -1; else if (s > rank) return 0; else {rank -= s;return 1;} } void splay(Node *&x,int rank) { pushdown(x); int d = Judge(x,rank); if (d == -1) return; pushdown(x->ch[d]); int d2 = Judge(x->ch[d],rank); if (d2 != -1) { splay(x->ch[d]->ch[d2],rank); if (d != d2) rotate(x->ch[d],d2); else rotate(x,d); } rotate(x,d); } void split(Node *&x,int rank,Node *&left,Node *&right) { splay(x,rank); right = x->ch[1]; x->ch[1] = NULL; maintain(x); left = x; } Node *merge(Node *&x,Node *&y) { splay(x,x->siz); x->ch[1] = y; maintain(x); return x; } void Delete(Node *&x) { for (int i = 0; i < 2; i++) if (x->ch[i] != NULL) Delete(x->ch[i]); x->ch[0] = x->ch[1] = NULL; sta[++cnt] = x->po; x = NULL; } Node *NEW() { Node *ret = &pool[sta[cnt]]; ret->po = sta[cnt--]; ret->l = ret->r = ret->num = ret->MAX = ret->rev = ret->siz = ret->sum = 0; ret->modi = INF; return ret; } int GETCOM() { scanf("%s",cha); if (cha[0] == 'I') return 1; if (cha[0] == 'D') return 2; if (cha[0] == 'R') return 4; if (cha[0] == 'G') return 5; int len = strlen(cha); if (len == 7) return 6; else return 3; } Node *Insert(Node *&x,int l,int r) { int mid = (l+r) >> 1; x = NEW(); x->num = a[mid]; if (l != mid) x->ch[0] = Insert(x->ch[0],l,mid-1); if (mid < r) x->ch[1] = Insert(x->ch[1],mid+1,r); maintain(x); return x; } void PREWORK(Node *&left,Node *&right) { split(root,pos+tot,left,right); maintain(left); splay(left,pos); } int main() { #ifdef YZY freopen("yzy.txt","r",stdin); #endif cin >> n >> m; for (int i = 1; i <= 500001; i++) sta[i] = i; cnt = 500001; for (int i = 1; i <= n; i++) scanf("%d",&a[i]); root = NEW(); root->ch[1] = Insert(root->ch[1],1,n); maintain(root); ++n; for (int l = 1; l <= m; l++) { int typ = GETCOM(); if (typ == 6) { splay(root,1); if (root->ch[1] != NULL) printf("%d\n",root->ch[1]->MAX); //else printf("0\n"); continue; } Node *left,*right; scanf("%d%d",&pos,&tot); if (!tot) {if (typ == 5) printf("0\n"); continue;} if (typ == 1) { for (int i = 1; i <= tot; i++) scanf("%d",&a[i]); split(root,pos+1,left,right); left->ch[1] = Insert(left->ch[1],1,tot); maintain(left); root = merge(left,right); n += tot; } else if (typ == 2) { PREWORK(left,right); Delete(left->ch[1]); maintain(left); root = merge(left,right); n -= tot; } else if (typ == 3) { PREWORK(left,right); int c; scanf("%d",&c); Node *&x = left->ch[1]; x->num = x->modi = c; x->sum = c*x->siz; if (c > 0) x->l = x->r = x->MAX = x->sum; else x->l = x->r = 0,x->MAX = c; maintain(left); root = merge(left,right); } else if (typ == 4) { PREWORK(left,right); Node *&x = left->ch[1]; swap(x->ch[0],x->ch[1]); swap(x->l,x->r); x->rev ^= 1; maintain(left); root = merge(left,right); } else { PREWORK(left,right); printf("%d\n",left->ch[1]->sum); root = merge(left,right); } } return 0; }