数列维护 NOI2005

http://www.lydsy.com/JudgeOnline/problem.php?id=1500

很磨人的题,如果对splay的push_up和push_down理解不透彻的话debug过程会很痛苦的,一定要注意及时把信息更新的根节点,还有就是这题要求至少选择一个数。


/*

30
1000
-505
467
-773
-521
808
-690
939
-962
-490
-688
-878
254
-811
120
-866
132
-771
830
-761
139
-692
-336
63
-410
486
-828
922
981
738
-94

DELETE
3
5

GET-SUM
10
9

GET-SUM
10
9

INSERT
22
6
-145
928
-886
399
403
-252

GET-SUM
27
3

GET-SUM
18
10

DELETE
7
6

GET-SUM
12
7

MAKE-SAME
9
7
-742

INSERT
5
7
-758
920
-96
417
-813
136
-899

DELETE
22
5

INSERT
5
9
-4
893
-312
-22
-72
641
727
130
613

REVERSE
18
1

MAKE-SAME
31
5
807

MAX-SUM

MAKE-SAME
6
6
-939

REVERSE
1
36

INSERT
36
9
-965
-750
-344
-27
511
762
-34
462
907

MAKE-SAME
11
7
864

DELETE
8
7

GET-SUM
5
7

REVERSE
1
17

REVERSE
7
21

MAX-SUM

*/


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;

const int MAXN(500015);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI((INT_MAX-1) >> 1);
const int MOD(10000);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);


int value[MAXN];

struct SPLAY_TREE
{
	struct NODE
	{
		int num, size, flag1, flag2;  
		int lsum, rsum, msum, sum;
		NODE *fa;
		NODE *ch[2];
	};

	NODE pool[MAXN];
	NODE *rec[MAXN];
	int top;
	NODE *root, *NIL, *rear, *ll, *rl;
	inline void push_up(NODE *sour)  //一定要注意NIL节点对push_up的影响
	{
		NODE *lc = sour->ch[0], *rc = sour->ch[1];
		sour->size = lc->size+rc->size+1;
		sour->sum = lc->sum+rc->sum+sour->num;
		sour->msum = max( max(lc->msum, rc->msum), 
					      max(max(lc->rsum+sour->num, rc->lsum+sour->num), 
						      max(lc->rsum+rc->lsum+sour->num, sour->num)
					         )
						);
		sour->lsum = max(lc->lsum, max(lc->sum+sour->num, lc->sum+sour->num+rc->lsum));
		sour->rsum = max(rc->rsum, max(rc->sum+sour->num, rc->sum+sour->num+lc->rsum));
	}
	inline void updata_same(NODE *sour, int v)
	{
		if(sour == NIL) return;
		sour->sum = sour->size*v;
		sour->lsum = sour->rsum = sour->msum = (v > 0? v*sour->size: v);
		sour->num = v;
		sour->flag1 = v;
	}
	inline void updata_rev(NODE *sour)
	{
		if(sour == NIL) return;
		swap(sour->ch[0], sour->ch[1]);
		swap(sour->lsum, sour->rsum);
		sour->flag2 ^= 1;
	}
	void push_down(NODE *sour)  //和线段树的push_down一样,是对子节(注意不是本节点)进行更新
	{
		if(sour->flag1 != INV)
		{
			updata_same(sour->ch[0], sour->flag1);
			updata_same(sour->ch[1], sour->flag1);
			sour->flag1 = INV;
		}
		if(sour->flag2)
		{
			updata_rev(sour->ch[0]);
			updata_rev(sour->ch[1]);
			sour->flag2 = 0;
		}
	}
	void initNIL()
	{
		NIL->ch[0] = NIL->ch[1] = NIL->fa = NIL;
		NIL->num = NIL->lsum = NIL->rsum = NIL->msum = -1000000;  //为了防止NIL对push_up造成影响
		NIL->size = NIL->sum = 0;								   //为了防止NIL对push_up造成影响
	}

	void init(int n)
	{
		NIL = pool;
		initNIL();
		rear = pool+1;
		top = 0;
		newnode(root, NIL, -100000);  //插入无穷小
		newnode(root->ch[1], root, 100000); //插入无穷大
		build_tree(root->ch[1]->ch[0], root->ch[1], 1, n); //建树
		push_up(root->ch[1]);
		push_up(root);
	}

	void newnode(NODE *&sour, NODE *f, int num)
	{
		if(top)
			sour = rec[--top];
		else
			sour = rear++;
		sour->num = num;
		sour->size = 1;
		sour->flag1 = INV;
		sour->flag2 = 0;
		sour->lsum = sour->rsum = sour->msum = sour->sum = num;
		sour->fa = f;
		sour->ch[0] = sour->ch[1] = NIL;
	}

	void build_tree(NODE *&sour, NODE *f, int l, int r)
	{
		if(l > r)
			return;
		int m = (l+r) >> 1;
		newnode(sour, f, value[m]);
		build_tree(sour->ch[0], sour, l, m-1);
		build_tree(sour->ch[1], sour, m+1, r);
		push_up(sour);
	}

	void rotate(NODE *sour, int flag)
	{
		NODE *f = sour->fa;
		push_down(f);
		push_down(sour);
		f->ch[!flag] = sour->ch[flag];
		sour->ch[flag]->fa = f;
		sour->fa = f->fa;
		if(f->fa != NIL)
			f->fa->ch[f->fa->ch[1] == f] = sour;
		sour->ch[flag] = f;
		f->fa = sour;
		push_up(f);
	}
	
	void splay(NODE *sour, NODE *goal)
	{
		push_down(sour);
		while(sour->fa != goal)
		{
			if(sour->fa->fa == goal)
				rotate(sour, sour->fa->ch[0] == sour);
			else
			{
				NODE *f = sour->fa;
				int flag = (f->fa->ch[0] == f);
				if(f->ch[flag] == sour)
					rotate(sour, !flag);
				else
					rotate(f, flag);
				rotate(sour, flag);
			}
		}
		push_up(sour);
		if(goal == NIL)
			root = sour;
	}

	NODE *select(NODE *sour, int r)
	{
		while(true)
		{
			push_down(sour);
			if(r == sour->ch[0]->size+1)
				break;
			if(r <= sour->ch[0]->size)
				sour = sour->ch[0];
			else
			{
				r -= sour->ch[0]->size+1;
				sour = sour->ch[1];
			}
		}
		return sour;
	}

	void FREE(NODE *sour)
	{
		if(sour == NIL)
			return;
		FREE(sour->ch[0]);
		FREE(sour->ch[1]);
		rec[top++] = sour;
	}

	void INSERT(int pos, int n)
	{
		NODE *tp;
		tp = select(root, pos+1);
		splay(tp, NIL);
		tp = select(root, pos+2);
		splay(tp, root);
		build_tree(tp->ch[0], tp, 1, n);
		push_up(root->ch[1]);
		push_up(root);
	}

	void DELETE(int pos, int n)
	{
		NODE *tp;
		tp = select(root, pos);
		splay(tp, NIL);
		tp = select(root, pos+1+n);
		splay(tp, root);
		FREE(tp->ch[0]);
		tp->ch[0] = NIL;
		push_up(root->ch[1]);
		push_up(root);
	}

	void MAKE_SAME(int pos, int n, int c)
	{
		NODE *tp;
		tp = select(root, pos);
		splay(tp, NIL);
		tp = select(root, pos+1+n);
		splay(tp, root);
		updata_same(tp->ch[0], c);
		push_up(root->ch[1]);
		push_up(root);
	}

	void REVERSE(int pos, int n)
	{
		NODE *tp;
		tp = select(root, pos);
		splay(tp, NIL);
		tp = select(root, pos+1+n);
		splay(tp, root);
		updata_rev(tp->ch[0]);
		push_up(root->ch[1]);
		push_up(root);
	}

	int GET_SUM(int pos, int n)
	{
		NODE *tp;
		tp = select(root, pos);
		splay(tp, NIL);
		tp = select(root, pos+1+n);
		splay(tp, root);
		return tp->ch[0]->sum;
	}

	int MAX_SUM()
	{
		NODE *tp;
		tp = select(root, 1);
		splay(tp, NIL);
		tp = select(root, root->size);
		splay(tp, root);
		return tp->ch[0]->msum;
	}
};

SPLAY_TREE spt;

char str[20];

int main()
{
	int n, m;
//	freopen("d:\\out.txt", "w", stdout);
	while(~scanf("%d%d", &n, &m))
	{
		for(int i = 1; i <= n; ++i)
			scanf("%d", value+i);
		spt.init(n);
		int pos, tn, temp;
		for(int j = 0; j < m; ++j)
		{
	//		spt.debug();
			scanf("%s", str);
			if(strcmp(str, "INSERT") == 0)
			{
				scanf("%d%d", &pos, &tn);
				for(int i = 1; i <= tn; ++i)
					scanf("%d", value+i);
				spt.INSERT(pos, tn);
			}
			else if(strcmp(str, "DELETE") == 0)
			{
				scanf("%d%d", &pos, &tn);
				spt.DELETE(pos, tn);
			}
			else if(strcmp(str, "MAKE-SAME") == 0)
			{
				scanf("%d%d%d", &pos, &tn, &temp);
				spt.MAKE_SAME(pos, tn, temp);
			}
			else if(strcmp(str, "REVERSE") == 0)
			{
				scanf("%d%d", &pos, &tn);
				spt.REVERSE(pos, tn);
			}
			else if(strcmp(str, "GET-SUM") == 0)
			{
				scanf("%d%d", &pos, &tn);
				printf("%d\n", spt.GET_SUM(pos, tn));
			}
			else
				printf("%d\n", spt.MAX_SUM());
		}
	}
	return 0;
}


你可能感兴趣的:(数列维护 NOI2005)