lydsy 1500 [NOI2005]维修数列 (Treap版)
来源:互联网 发布:百中搜优化 编辑:程序博客网 时间:2024/05/29 15:35
题意: 数列兄出来受死吧。。这次要求支持插入,删除,区间修改,区间翻转,区间求和,求和最大的子列的和。
解法: 没什么能说的了,一些细节写在了注释里。
/* **********************************************Author : NeroCreated Time: 2013/9/5 16:51:21Problem id : lydsy 1500Problem Name: [NOI2005]维修数列 *********************************************** */#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define REP(i,a,b) for(int i=(a); i<(int)(b); i++)#define clr(a,b) memset(a,b,sizeof(a))struct Node { Node *l, *r; int v,sum,size; int lms,rms,tms; int cover,rev,w; void up() { sum = tms = lms = rms = v; size = 1; if(l) sum += l->sum, size += l->size; if(r) sum += r->sum, size += r->size; // 处理左端最大和 if(l) { lms = l->lms; lms = max(lms, l->sum + v); if(r) lms = max(lms, l->sum + v + r->lms); } else if(r) { lms = max(lms, v + r->lms); } // 处理右端最大和 if(r) { rms = r->rms; rms = max(rms, r->sum + v); if(l) rms = max(rms, r->sum + v + l->rms); } else if(l) { rms = max(rms, v + l->rms); } // 处理子段最大和 if(l) { tms = max(tms, l->tms); tms = max(tms, l->rms + v); } if(r) { tms = max(tms, r->tms); tms = max(tms, r->lms + v); } if(l && r) tms = max(tms, l->rms + v + r->lms); } void down() { if(cover) { if(l) { l->v = v; l->sum = v * l->size; if(v >= 0) l->lms = l->rms = l->tms = l->sum; else l->lms = l->rms = l->tms = v; l->cover = 1; } if(r) { r->v = v; r->sum = v * r->size; if(v >= 0) r->lms = r->rms = r->tms = r->sum; else r->lms = r->rms = r->tms = v; r->cover = 1; } cover = 0; } // 注意处理翻转时左右端最大值也要交换 // lazy的思想是在保证当前节点和两个子节点的信息真实的情况下尽量偷懒 if(rev) { swap(l,r); if(l) l->rev ^= 1,swap(l->lms,l->rms); if(r) r->rev ^= 1,swap(r->lms,r->rms); rev = 0; } }}*root = NULL, *list = NULL;// 节点的回收重复利用// fhq神牛的随机数生成器- -int ran() { static int ranx = 123654789; ranx += (ranx << 2) + 1; return ranx;}void New_node(Node *&o, int val) { if(list == NULL) { Node *tt = new Node[10000]; for(int i = 0; i < 10000; i ++) { tt[i].r = list; tt[i].w = ran(); list = tt + i; } } o = list; list = list->r; o->l = o->r = NULL; o->v = o->sum = o->lms = o->rms = o->tms = val; o->rev = o->cover = 0; o->size = 1;}void Reuse(Node *o) { if(o == NULL) return ; Reuse(o->l); Reuse(o->r); o->r = list; list = o;}inline int sz(Node *o) { return o ? o->size : 0; }// 砍树void cut(Node *o, Node *&p, Node *&q, int num) { if(num == 0) { p = NULL; q = o; } else if(num == sz(o)) { p = o; q = NULL; } else { o->down(); if(sz(o->l) >= num) { q = o; cut(o->l, p, q->l, num); q->up(); } else { p = o; cut(o->r, p->r, q, num - sz(o->l) - 1); p->up(); } }}// 合并void merge(Node *&o, Node *p, Node *q) { if(!p || !q) { o = p ? p : q; } else { if(p->w > q->w) { p->down(); o = p; merge(o->r, p->r, q); } else { q->down(); o = q; merge(o->l, p, q->l); } o->up(); }}// 递归插入,否则每次都合并太深要超时Node* Ins(int x) { if(x == 0) return NULL; if(x == 1) { int d; Node *a; scanf("%d", &d); New_node(a,d); return a; } Node *a, *b; int m = x >> 1; a = Ins(m); b = Ins(x-m); merge(a,a,b); return a;}// 在第pos个数后面插入x个数void Insert(int pos, int x) { int d; Node *a, *b, *c, *t; cut(root,a,b,pos); c = Ins(x); merge(a,a,c); merge(root,a,b);}// 从第pos个数开始连续删x个数void Remove(int pos, int x) { Node *a, *b, *c; cut(root,a,b,pos-1); cut(b,b,c,x); Reuse(b); merge(root,a,c);}// 将第pos个数开始的x个数位置翻转void Reverse(int pos, int x) { Node *a, *b, *c; cut(root,a,b,pos-1); cut(b,b,c,x); b->rev ^= 1; swap(b->lms,b->rms); merge(a,a,b); merge(root,a,c);}// 求第pos个数开始的连续x个数的和int Get_sum(int pos, int x) { if(x == 0) return 0; Node *a, *b, *c; cut(root,a,b,pos-1); cut(b,b,c,x); int ret = b->sum; merge(a,a,b); merge(root,a,c); return ret;}// 将第pos个数开始的x个数修改为dvoid Change(int pos, int x, int d) { Node *a, *b, *c; cut(root,a,b,pos-1); cut(b,b,c,x); b->v = d; b->cover = 1; b->rev = 0; b->sum = d * sz(b); if(d >= 0) b->lms = b->tms = b->rms = b->sum; else b->lms = b->tms = b->rms = d; merge(a,a,b); merge(root,a,c);}int main() { int n,m,x,pos,c; char s[20]; scanf("%d%d", &n, &m); Insert(0,n); while(m --) { scanf("%s", s); if(s[0] == 'I') { scanf("%d%d", &pos, &x); if(x != 0) Insert(pos,x); } else if(s[0] == 'D') { scanf("%d%d", &pos, &x); if(x != 0) Remove(pos,x); } else if(s[0] == 'R') { scanf("%d%d", &pos, &x); if(x > 1) Reverse(pos,x); } else if(s[0] == 'G') { scanf("%d%d", &pos, &x); printf("%d\n", Get_sum(pos,x)); } else if(s[2] == 'K') { scanf("%d%d%d", &pos, &x, &c); if(x != 0) Change(pos,x,c); } else { if(root == NULL) puts("0"); else printf("%d\n", root->tms); } } return 0;}
- lydsy 1500 [NOI2005]维修数列 (Treap版)
- 1500: [NOI2005]维修数列
- 1500: [NOI2005]维修数列
- 1500: [NOI2005]维修数列
- 1500: [NOI2005]维修数列
- 【BZOJ】【P1500】【NOI2005】【维修数列】【题解】【Treap】
- 【BZOJ 1500】 [NOI2005]维修数列
- 1500: [NOI2005]维修数列(Splay)
- BZOJ 1500: [NOI2005]维修数列
- BZOJ 1500[NOI2005] 维修数列
- BZOJ 1500[NOI2005] 维修数列
- BZOJ 1500: [NOI2005] 维修数列
- BZOJ 1500 [NOI2005]维修数列
- BZOJ 1500 [NOI2005]维修数列
- BZoj 1500 [NOI2005]维修数列 (Splay 模板)
- BZOJ 1500 NOI2005 维修数列 Splay
- 【BZOJ】1500 [NOI2005]维修数列 【splay】
- 【splay】BZOJ 1500: [NOI2005]维修数列
- 关于裁员思考-素老胡huxingyu
- 数据结构作业
- 【 2028 Lowest Common Multiple Plus】
- 实时Bug检测工具-Bugsnag的使用
- 异常
- lydsy 1500 [NOI2005]维修数列 (Treap版)
- nginx之core_module主要实现功能
- WPF中获取TreeView以及ListView获取其本身滚动条的方法,可实现自行调节scoll滚动的位置
- 收藏夹工具seo
- Spring + mybatis整合方案总结 结合实例应用
- logcat使用
- 通过计算结果从当前Activity跳转到下一个Activity
- 常见的Java语法面试真题
- C语言中 sizeof 与 struct