1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 10809 Solved: 3367
[ Submit][ Status][ Discuss]
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
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
10
1
10
HINT
Source
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;
}