339. [NOI2005] Maintenance series
★★★★☆ input file: seq2005.in output file: Seq2005.out Simple contrast
time limit: 3 s memory limit:
"Problem description"
Please write a program that requires maintaining a sequence that supports the following 6 actions: (Note that the underscore ' _ ' in the format bar represents a space in the actual input file)
"input Format"
The 1th line of the input file contains two numbers N and M,n indicates the number of numbers in the initial sequence, and M represents the number of operations to be performed.
Line 2nd contains N numbers that describe the initial sequence.
The following M lines, one command per line, are shown in the table in the problem description.
"Output format"
For Get-sum and max-sum operations in the input data, print the results sequentially to the output file, one row for each answer (number).
"Input Sample"
9 8
2-6 3 5 1-5-3 6 3
get-sum 5 4
max-sum INSERT 8 3-5 7 2
DELETE 1
make-same 3 3 2
R Everse 3 6
get-sum 5 4
Max-sum
"output Example"
-1
1
10
"Sample description"
Initially, we have a sequence of 2-6 3 5 1-5-3 6 3
Perform Operation Get-sum 5 4 to find out the sum of 4 consecutive numbers starting from the 5th number in the sequence, 1+ (-5) + (-3) +6 =-1:
2 -6 3 5 1-5-3 6 3
Perform operation Max-sum, indicating that the largest segment of the current sequence is required and should be 3+5+1+ (-5) + (-3) +6+3 = 10:
2 -6 3 5 1-5-3 6 3
To do this, insert 8 3-5 7 2, which is inserted after the 8th digit in the sequence-5 7 2,
2 -6 3 5 1-5-3 6-5 7 2 3
Perform the action delete 12 1, which indicates the deletion of the 12th digit, that is, the last one:
2 -6 3 5 1-5-3 6-5 7 2
Perform action Make-same 3 3 2, which represents 3 numbers starting from the 3rd number, uniformly modified to 2:
2 -6 3 5 1-5-3 6-5 7 2
Switch
2 -6 2 2 2-5-3 6-5 7 2
Perform action REVERSE 3 6, which indicates that the number of 6 consecutive numbers starting from the 3rd number in the sequence is removed:
2 -6 2 2 2-5-3 6-5 7 2
As shown in the gray Section 2 2 2-5-3 6, flipped to get 6-3-5 2 2 2, and put back the original position:
2 -6 6-3-5 2 2 2-5 7 2
Finally executed Get-sum 5 4 and max-sum, not difficult to get answers 1 and 10.
2 -6 6-3-5 2 2 2-5 7 2
"Scoring Method"
The subject has partial points, for each test point:
If your program can print the answer to the get-sum operation in the correct location of the output file, you can get the score of the test point 60%;
If your program can print the answer to the max-sum operation in the correct location of the output file, you can get the score of the test point 40%;
The above two points can be superimposed, i.e. if your program correctly outputs all get-sum and max-sum operation answers, you can get the score of the test point 100%.
Note: If your program only handles one operation correctly, make sure that you print the results in the correct location of the output file, that is, you must leave the corresponding row for another operation, otherwise we do not guarantee that the score will be correct.
"Data size and conventions"
You can think of at least 1 numbers in a sequence at any given moment.
The input data must be correct, that is, the number of the specified position must exist in the sequence.
50% of the data, at any time the number of columns in a maximum of 30 000;
In 100% of the data, there is a maximum of 500 000 numbers in a sequence at any time.
In 100% of the data, any number in the sequence is within [-1 000, 1 000].
100% of the data, M≤20 000, the total number of inserted not more than 4 000 000, the input file size does not exceed 20MBytes.
The following:
A very comprehensive interval operation problem, a god Ben said within 1 hours to write a off the basic interval problem can be worry-free. But I was too weak to write a 4h+.
The information that each node needs to save:
V: Point right; p: Key value; CNT: repeat (or not); SZ: sub-tree size; sum: Interval point right and;
LS: The largest continuous interval extending from the far left;
RS: Maximum continuous interval extending from the far right;
MAXS: The maximal continuous interval of the whole interval and;
Rev: Reversal Mark; C: Modify Mark;
Maintenance:
Ls=max (Left->ls,left->sum+x->v+max (0,r->ls));
Rs=max (Right->rs,max (0,LEFT->RS) +x->v+right->sum);
Maxs=max (Max (0,left->rs) +x->v+max (0,right->ls), Max (LEFT->MAXS,RIGHT->MAXS));
Flips the swap subtree and ls,rs.
Just take a look at the specifics.
Insert: Violence inserts each number.
Delete: Deletes the interval. can write garbage collection. But I was lazy to write.
Make-same: Marking, to be decentralized.
Reverse: Marking, the same way to devolve.
Get-sum: Find the interval, direct query can.
Max-sum: Direct root node maxs can be found.
Code:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath
> #include <algorithm> #define INF-0X7FFFFFFF using namespace std;
struct node{node *left,*right;
int v,p,sz,cnt,sum,ls,rs,maxs,rev,c;
}*root,*null=new node ((node) {null,null,0,0,0,0,inf,inf,inf,inf,0,inf});
typedef pair<node*,node*> Dnode;
void Push_up (node *x) {node *l=x->left,*r=x->right;
x->sz=x->cnt+l->sz+r->sz;
Sum x->sum=x->v;
if (L->SZ) x->sum+=l->sum;
if (R->SZ) x->sum+=r->sum;
ls if (l->sz) X->ls=max (L->ls,l->sum+x->v+max (0,r->ls));
Else X->ls=max (X->v,x->v+max (0,r->ls));
RS if (R->sz) X->rs=max (R->rs,max (0,L->RS) +x->v+r->sum);
Else X->rs=max (X->v,x->v+max (0,l->rs)); Maxs if (L->sz && r->sz) X->maxs=max (0,l->rs) +x->v+max (0,R->LS);
else {if (L->sz) X->maxs=max (l->rs,0) +x->v;
else if (R->sz) X->maxs=max (0,r->ls) +x->v;
else x->maxs=x->v;
} if (L->sz) X->maxs=max (X->MAXS,L->MAXS);
if (R->sz) X->maxs=max (X->MAXS,R->MAXS);
X->maxs=max (x->maxs,x->sum);
} void Push_down (node *x) {node *l=x->left,*r=x->right;
if (X->c!=inf) {if (L->sz) {l->c=l->v=x->c; l->sum=l->v*l->sz;
L->ls=l->rs=l->maxs=max (l->v,l->sum);
} if (R->sz) {r->c=r->v=x->c; r->sum=r->v*r->sz;
R->ls=r->rs=r->maxs=max (r->v,r->sum);
} x->c=inf;
} if (x->rev%2) {if (L->sz) {swap (l->left,l->right); Swap (L->LS,L->RS);
l->rev++;
} if (R->sz) {swap (r->left,r->right); Swap (R->LS,R->RS);
r->rev++;
} x->rev=0;
}} node *merge (node *x,node *y) {if (!x->sz) return y;
if (!Y->SZ) return x; Push_down (x);
Push_down (y);
if (x->p<y->p) {x->right=merge (x->right,y); PUSH_UP (x);
return x;
} else {y->left=merge (x,y->left); Push_up (y);
return y;
}} Dnode Split (node *x,int k) {if (!x->sz) return Dnode (Null,null);
Dnode y;
Push_down (x);
if (K<=x->left->sz) {y=split (x->left,k);
x->left=y.second; PUSH_UP (x);
Y.second=x;
} else {y=split (x->right,k-x->left->sz-x->cnt);
x->right=y.first; PUSH_UP (x);
Y.first=x;
} return y;
} void Insert (int x,int k) {Dnode y=split (root,x); node *z;
for (int i=1; i<=k; i++) {int v; scanf ("%d", &v);
Z=new node;
z->v=z->sum=z->ls=z->rs=z->maxs=v; Z->left=z->right=null;
z->c=inf; z->sz=z->cnt=1; Z->p=rand ();
z->rev=0;
Y.first=merge (Y.FIRST,Z);
} root=merge (Y.first,y.second);
} void Delete (int x,int k) {Dnode y,z;
Y=split (root,x-1);
Z=split (Y.SECOND,K);
Root=merge (Y.first,z.second);
} void Change (int x,int K,int v) {Dnode y,z;
Y=split (root,x-1);
Z=split (Y.SECOND,K);
z.first->c=z.first->v=v;
z.first->sum=v*z.first->sz;
Z.first->ls=z.first->rs=z.first->maxs=max (v,z.first->sum);
Push_down (Z.first);
Y.second=merge (Z.first,z.second);
Root=merge (Y.first,y.second);
} void Reverse (int x,int k) {Dnode y,z;
Y=split (root,x-1);
Z=split (Y.SECOND,K);
z.first->rev++;
Swap (z.first->left,z.first->right);
Swap (Z.FIRST->LS,Z.FIRST->RS);
Push_down (Z.first);
Y.second=merge (Z.first,z.second);
Root=merge (Y.first,y.second);
} void Q_sum (int x,int k) {Dnode y,z; if (!k) {printf ("0\n");
Return
} y=split (root,x-1);
Z=split (Y.SECOND,K);
PUSH_UP (Z.first);
printf ("%d\n", z.first->sum);
Y.second=merge (Z.first,z.second);
Root=merge (Y.first,y.second);
} int main () {int n,m; root=null; char opt[20]; scanf ("%d%d", &n,&m);
Insert (0,n);
while (m--) {scanf ("%s", &opt); int x, y, Z; Switch (opt[0]) {case ' I ': scanf ("%d%d", &x,&y); Insert (x, y);
Break Case ' D ': scanf ("%d%d", &x,&y); Delete (x, y);
Break
Case ' M ': {if (opt[2]== ' K ') scanf ("%d%d%d", &x,&y,&z), change (x, y, z);
else printf ("%d\n", ROOT->MAXS);
Break } case ' R ': scanf ("%d%d", &x,&y); Reverse (x, y);
Break Case ' G ': scanf ("%d%d", &x,&y); Q_sum (x, y);
Break }//cout<<root->v<< "" <<root->p<< "" <<root->sz<< "" ≪<root->sum<< "<<root->ls<<" "<<root->rs<<" "<<root->maxs
<<endl;
} return 0; }