JZOJ2413 【NOI2005】维护数列
来源:互联网 发布:windows 2000 编辑:程序博客网 时间:2024/06/12 21:15
Description
请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线‘ _ ’表示实际输入文件中的空格)
1. 插入 INSERT_posi_tot_c1_c2_…_ctot 在当前数列的第posi个数字后插入tot个数字:c1, c2, …, ctot;若在数列首插入,则posi为0
2. 删除 DELETE_posi_tot 从当前数列的第posi个数字开始连续删除tot个数字
3. 修改 MAKE-SAME_posi_tot_c 将当前数列的第posi个数字开始的连续tot个数字统一修改为c
4. 翻转 REVERSE_posi_tot 取出从当前数列的第posi个数字开始的tot个数字,翻转后放入原来的位置
5. 求和 GET-SUM_posi_tot 计算从当前数列开始的第posi个数字开始的tot个数字的和并输出
6. 求和最大的子列 MAX-SUM 求出当前数列中和最大的一段子列,并输出最大和
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
Data Constraint
你可以认为在任何时刻,数列中至少有1个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有30 000个数;
100%的数据中,任何时刻数列中最多含有500 000个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Hint
题目大意:
略。
题解:
据说这是一道splay的初级毕业题,也是NOI出过的最恶心的数据结构题之一。
查询有两种:求和 和 最大子区间和。
求和就不用说了。
最大子区间和我们需要维护3个值:
a.从区间左端点开始的最大和。
b.从区间右端点开始的最大和。
c.整个区间的子区间最大和。
转移a,b非常简单,c就考虑两个子树分别的子区间最大和 和 把两个区间合并起来的最大和,类似于线段树。
插入,删除很好维护。
区间翻转就把指针交换,再把a,b交换,c的值是不会变的。
对于区间赋值,我们需要记录子树的大小,这样就可以快速得到a,b,c三个的值。
如果有这么简单也不错.
坑点:
把翻转标记打在x点上,必须是已经把x的左右指针 和 a,b交换过,否则会出bug。
区间赋值的标记的NULL值不能为0,因为有可能把整个区间变成0.
Code:
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define fo(i, x, y) for(int i = x; i <= y; i ++)#define max(a, b) ((a) > (b) ? (a) : (b))using namespace std;const int Maxn = 1000005, INF = 1e8;int root, n, m, fa[Maxn], t[Maxn][2], p[Maxn], d[Maxn];struct node { int z, sum, ms, ls, rs, lz1, lz2, siz;}a[Maxn];int read(int &x) { char ch = ' '; for(; ch != '-' && (ch < '0' || ch > '9');) ch = getchar(); int f = 1; x = 0; if(ch == '-') f = -1, ch = getchar(); for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - 48; return x *= f;}void update(int x) { if(!x) return; a[x].siz = a[t[x][0]].siz + a[t[x][1]].siz + 1; a[x].sum = a[t[x][0]].sum + a[t[x][1]].sum + a[x].z; a[x].ls = max(a[t[x][0]].ls, a[t[x][0]].sum + a[t[x][1]].ls + a[x].z); a[x].ls = max(a[x].ls, a[t[x][0]].sum + a[x].z); a[x].rs = max(a[t[x][1]].rs, a[t[x][1]].sum + a[t[x][0]].rs + a[x].z); a[x].rs = max(a[x].rs, a[t[x][1]].sum + a[x].z); a[x].ms = max(a[t[x][0]].ms, a[t[x][1]].ms); a[x].ms = max(a[x].ms, a[t[x][0]].rs + a[t[x][1]].ls + a[x].z); a[x].ms = max(a[x].ms ,a[t[x][0]].rs + a[x].z); a[x].ms = max(a[x].ms, a[t[x][1]].ls + a[x].z); a[x].ms = max(a[x].ms, a[x].z);}int lr(int x) {return t[fa[x]][1] == x;}void chan1(int x) { if(!x) return; swap(t[x][0], t[x][1]); swap(a[x].ls, a[x].rs); a[x].lz1 ^= 1;}void chan2(int x, int y) { if(!x) return; a[x].z = y, a[x].sum = a[x].siz * y; a[x].ms = a[x].ls = a[x].rs = (y > 0) ? (y * a[x].siz) : y; a[x].lz2 = y;}void down(int x) { if(!x) return; if(a[x].lz1) chan1(t[x][0]), chan1(t[x][1]), a[x].lz1 = 0; if(a[x].lz2 != INF) chan2(t[x][0], a[x].lz2), chan2(t[x][1], a[x].lz2), a[x].lz2 = INF;}void rotate(int x) { int y = fa[x], k = lr(x); t[y][k] = t[x][!k]; if(t[x][!k]) fa[t[x][!k]] = y; fa[x] = fa[y]; if(fa[y]) t[fa[y]][lr(y)] = x; t[x][!k] = y; fa[y] = x; update(y);}void xc(int x) { while(x) p[++ p[0]] = x, x = fa[x]; for(; p[0]; p[0] --) down(p[p[0]]);}void splay(int x, int y) { xc(x); while(fa[x] != y) { if(fa[fa[x]] != y) if(lr(fa[x]) == lr(x)) rotate(fa[x]); else rotate(x); rotate(x); } update(x);}int find(int x, int y) { down(x); if(a[t[x][0]].siz >= y) return find(t[x][0], y); if(a[t[x][0]].siz + 1 == y) return x; return find(t[x][1], y - a[t[x][0]].siz - 1);}void Init() { fo(i, 1, 1000000) a[i].lz2 = INF; read(n); read(m); a[0].ms = a[0].ls = a[0].rs = a[1].z = a[n + 2].z = -INF; a[1].siz = 1; fo(i, 1, n) { read(a[i + 1].z); a[i + 1].sum = a[i + 1].ls = a[i + 1].rs = a[i + 1].ms = a[i + 1].z; fa[i] = i + 1; t[i + 1][0] = i; update(i + 1); } fa[n + 1] = n + 2; t[n + 2][0] = n + 1; update(n + 2); d[0] = 500000 - n; fo(i, n + 2, n + d[0] + 1) d[i - n - 1] = i;}void back(int x) { if(!x) return; back(t[x][0]); back(t[x][1]); d[++ d[0]] = x; t[x][0] = t[x][1] = a[x].lz1 = fa[x] = 0; a[x].lz2 = INF;}void dg(int x) { if(!x) return; printf("%d %d %d\n", x, t[x][0], t[x][1]); dg(t[x][0]); dg(t[x][1]);}void Work() { root = n + 2; fo(T, 1, m) { char s[20]; scanf("%s", s); int posi, tot, c; if(s[0] == 'I') { read(posi); read(tot); int x = find(root, posi + 1), y = find(root, posi + 2); splay(x, 0); splay(y, x); int z = d[d[0] --]; read(a[z].z); a[z].siz = 1; a[z].sum = a[z].ms = a[z].ls = a[z].rs = a[z].z; fa[z] = y; t[y][0] = z; update(y); int last = z; fo(i, 2, tot) { z = d[d[0] --]; read(a[z].z); a[z].siz = 1; a[z].sum = a[z].ms = a[z].ls = a[z].rs = a[z].z; fa[z] = last; t[last][1] = z; update(last); last = z; } splay(z, 0); root = z; } if(s[0] == 'D') { read(posi); read(tot); int xx = find(root, posi), yy = find(root, posi + tot + 1); splay(xx, 0); splay(yy, xx); root = xx; back(t[yy][0]), t[yy][0] = 0; update(yy); update(xx); } if(s[0] == 'M' && s[2] == 'K') { read(posi); read(tot); read(c); int xx = find(root, posi), yy = find(root, posi + tot + 1); splay(xx, 0); splay(yy, xx); chan2(t[yy][0], c); root = t[yy][0]; splay(root, 0); } if(s[0] == 'R') { read(posi); read(tot); int xx = find(root, posi), yy = find(root, posi + tot + 1); splay(xx, 0); splay(yy, xx); chan1(t[yy][0]); root = t[yy][0]; splay(root, 0); } if(s[0] == 'G') { read(posi); read(tot); int xx = find(root, posi), yy = find(root, posi + tot + 1); splay(xx, 0); splay(yy, xx); root = xx; printf("%d\n", a[t[yy][0]].sum); } if(s[0] == 'M' && s[2] == 'X') { printf("%d\n", a[root].ms); } }}int main() { freopen("2413.in", "r", stdin); freopen("2413.out", "w", stdout); Init(); Work();}
- JZOJ2413. 【NOI2005】维护数列
- JZOJ2413 【NOI2005】维护数列
- 【jzoj2413】【NOI2005】【维护数列】【splay】
- 【noi2005】维护数列
- [NOI2005] 维护数列 sequence
- 【NOI2005】【splay】维护数列
- 数列维护 NOI2005
- 【SPLAY】NOI2005 维护数列
- 【noi2005】维护数列
- NOI2005维护数列
- noi2005维护数列 splay
- 【NOI2005】维护数列
- 【NOI2005】维护数列
- [NOI2005] 维护数列
- [题解]NOI2005 维护数列
- noi2005维护数列
- 【NOI2005】维护数列(BSOI2246)
- [NOI2005]维护数列
- POJ3258-River Hopscotch
- Android 添加多张图片。
- Struts1框架七之DispatchAction的说明
- 关于广义表
- GDI波形图的绘制以及坐标系的添加
- JZOJ2413 【NOI2005】维护数列
- MySQL基本操作
- 【JavaSE系列-入门篇4】——使用NetBeans IDE创建Hello World 应用程序
- 函数指针与回调函数
- python文件读写
- kuangbin [简单搜索专题]
- Struts2与Struts1.x的深度比较
- jQuery 属性操作和样式函数
- VR系列——Oculus Rift 开发者指南:三、Oculus Rift的渲染(二)