zoukankan      html  css  js  c++  java
  • 【bzoj1500】[NOI2005]维修数列

    题目描述:


    输入:

    输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
    第2行包含N个数字,描述初始时的数列。
    以下M行,每行一条命令,格式参见问题描述中的表格。
    任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
    插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

    输出:
    对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

    样例输入:

    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

    样例输出:

    -1
    10
    1
    10

    题解:

    splay果体。

    immortalCO:用treap更快,而且还更好写。

    反正这题机房里的其他神犇都是1A+差不多1h写完的,而我蒟蒻调了整整三天才调出来。QAQ

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    #ifdef WIN32
    	#define LL "%I64d"
    #else
    	#define LL "%lld"
    #endif
    
    #ifdef CT
    	#define debug(...) printf(__VA_ARGS__)
    #else
    	#define debug(...)
    #endif
    
    #define R register
    #define getc() (S == T&&(T = (S = B) + fread(B, 1, 1<<15, stdin), S == T)?EOF: * S ++ )
    #define gmax(_a,  _b) ((_a) > (_b) ? (_a) : (_b))
    #define gmin(_a,  _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a,  _b) (_a < (_b) ? _a  =  (_b) : 0)
    #define cmin(_a,  _b) (_a > (_b) ? _a  =  (_b) : 0)
    char B[1<<15],  * S = B,  * T = B;
    inline int FastIn()
    {
    	R char ch;R int cnt = 0;R bool minus = 0;
    	while (ch = getc(), (ch < '0' || ch > '9') && ch !=  '-') ;
    	ch  ==  '-' ?minus = 1:cnt = ch-'0';
    	while (ch = getc(), ch >=  '0' && ch  <=  '9') cnt  =  cnt  *  10  +  ch - '0';
    	return minus?-cnt:cnt;
    }
    #define maxn 1000010
    int fa[maxn], ch[maxn][2], a[maxn], size[maxn], cnt;
    int sum[maxn], lmx[maxn], rmx[maxn], mx[maxn], v[maxn], id[maxn], root;
    bool rev[maxn], tag[maxn];
    inline void swap(int &a, int &b)
    {
    	R int tmp = a;a = b;b = tmp;
    }
    inline void update(R int x)
    {
    	R int ls = ch[x][0], rs = ch[x][1];
    	size[x] = size[ls] + size[rs] + 1;
    	sum[x] = sum[ls] + sum[rs] + v[x];
    	mx[x] = gmax(mx[ls], mx[rs]);
    	cmax(mx[x], lmx[rs] + rmx[ls] + v[x]);
    	lmx[x] = gmax(lmx[ls], sum[ls] + v[x] + lmx[rs]);
    	rmx[x] = gmax(rmx[rs], sum[rs] + v[x] + rmx[ls]);
    }
    inline void pushdown(R int x)
    {
    	R int ls = ch[x][0], rs = ch[x][1];
    	if (tag[x])
    	{
    		rev[x] = tag[x] = 0;
    		if (ls) tag[ls] = 1, v[ls] = v[x], sum[ls] = size[ls] * v[x];
    		if (rs) tag[rs] = 1, v[rs] = v[x], sum[rs] = size[rs] * v[x];
    		if (v[x]>= 0)
    		{
    			if (ls) lmx[ls] = rmx[ls] = mx[ls] = sum[ls];
    			if (rs) lmx[rs] = rmx[rs] = mx[rs] = sum[rs];
    		}
    		else
    		{
    			if (ls) lmx[ls] = rmx[ls] = 0, mx[ls] = v[x];
    			if (rs) lmx[rs] = rmx[rs] = 0, mx[rs] = v[x];
    		}	
    	}
    	if (rev[x])
    	{
    		rev[x] ^= 1; rev[ls] ^= 1; rev[rs] ^= 1;
    		swap(lmx[ls], rmx[ls]);swap(lmx[rs], rmx[rs]);
    		swap(ch[ls][0], ch[ls][1]); swap(ch[rs][0], ch[rs][1]);
    	}
    }
    inline void rotate(R int x)
    {
    	R int f = fa[x], gf = fa[f], d = ch[f][1] == x;
    	if (f == root) root = x;
    	(ch[f][d] = ch[x][d ^ 1]) > 0 ? fa[ch[f][d]] = f : 0;
    	(fa[x] = gf) > 0 ? ch[gf][ch[gf][1] == f] = x : 0;
    	fa[ch[x][d ^ 1] = f] = x;
    	update(f);
    }
    inline void splay(R int x, R int rt)
    {
    	while (fa[x] != rt)
    	{
    		R int f = fa[x], gf = fa[f];
    		if (gf != rt) rotate((ch[gf][1] == f) ^ (ch[f][1] == x) ? x : f);
    		rotate(x);
    	}
    	update(x);
    }
    void build(R int l, R int r, R int rt)
    {
    	if (l > r) return ;
    	R int mid = l + r >> 1, now = id[mid], last = id[rt];
    	if (l == r)
    	{
    		sum[now] = a[l];
    		size[now] = 1;
    		tag[now] = rev[now] = 0;
    		if (a[l] >= 0) lmx[now] = rmx[now] = mx[now] = a[l];
    		else lmx[now] = rmx[now] = 0, mx[now] = a[l];
    	}
    	else
    	{
    		build(l, mid - 1, mid);
    		build(mid + 1, r, mid);
    	}
    	v[now] = a[mid];
    	fa[now] = last;
    	update(now);
    	ch[last][mid >= rt] = now;
    }
    int find(R int x, R int rank)
    {
    	if (tag[x] || rev[x]) pushdown(x);
    	R int ls = ch[x][0], rs = ch[x][1], lsize = size[ls];
    	if (lsize + 1 == rank) return x;
    	if (lsize >= rank)
    		return find(ls, rank);
    	else
    		return find(rs, rank - lsize - 1);
    }
    inline int prepare(R int l, R int tot)
    {
    	R int x = find(root, l - 1), y = find(root, l + tot);
    	splay(x, 0);
    	splay(y, x);
    	return ch[y][0];
    }
    std::queue <int> q;
    inline void Insert(R int left, R int tot)
    {
    	for (R int i = 1; i <= tot; ++i ) a[i] = FastIn();
    	for (R int i = 1; i <= tot; ++i )
    		if (!q.empty()) id[i] = q.front(), q.pop();
    		else id[i] = ++cnt;
    	build(1, tot, 0);
    	R int z = id[(1 + tot) >> 1];
    	R int x = find(root, left), y = find(root, left + 1);
    	splay(x, 0);
    	splay(y, x);
    	fa[z] = y;
    	ch[y][0] = z;
    	update(y);
    	update(x);
    }
    void rec(R int x)
    {
    	if (!x) return ;
    	R int ls = ch[x][0], rs = ch[x][1];
    	rec(ls); rec(rs); q.push(x);
    	fa[x] = ch[x][0] = ch[x][1] = 0;
    	tag[x] = rev[x] = 0;
    }
    inline void Delete(R int l, R int tot)
    {
    	R int x = prepare(l, tot), f = fa[x];
    	rec(x); ch[f][0] = 0;
    	update(f); update(fa[f]);
    }
    inline void Makesame(R int l, R int tot, R int val)
    {
    	R int x = prepare(l, tot), y = fa[x];
    	v[x] = val; tag[x] = 1; sum[x] = size[x] * val;
    	if (val >= 0) lmx[x] = rmx[x] = mx[x] = sum[x];
    	else lmx[x] = rmx[x] = 0, mx[x] = val;
    	update(y); update(fa[y]);
    }
    inline void Reverse(R int l, R int tot)
    {
    	R int x = prepare(l, tot), y = fa[x];
    	if (!tag[x])
    	{
    		rev[x] ^= 1;
    		swap(ch[x][0], ch[x][1]);
    		swap(lmx[x], rmx[x]);
    		update(y); update(fa[y]);
    	}
    }
    inline void Query(R int l, R int tot)
    {
    	R int x = prepare(l, tot);
    	printf("%d
    ",sum[x] );
    }
    #define inf ((1 << 30))
    int main()
    {
    	R int n = FastIn(),  m = FastIn(), l, tot, val;
    	R char op, op2;
    	mx[0] = a[1] = a[n + 2] = -inf;
    	for (R int i = 2; i <= n + 1; i++ )
    	{
    		a[i] = FastIn();
    	}
    	for (R int i = 1; i <= n + 2; ++i) id[i] = i;
    	n += 2; cnt = n; root = (n + 1) >> 1;
    	build(1, n, 0);
    	for (R int i = 1; i <= m; i++ )
    	{
    		op = getc();
    		while (op < 'A' || op > 'Z') op = getc();
    		getc(); op2 = getc();getc();getc();getc();getc();
    		if (op == 'M' && op2 == 'X')
    		{
    			printf("%d
    ",mx[root] );
    		}
    		else
    		{
    			l = FastIn() + 1; tot = FastIn();
    			if (op == 'I') Insert(l, tot);
    			if (op == 'D') Delete(l, tot);
    			if (op == 'M') val = FastIn(), Makesame(l, tot, val);
    			if (op == 'R')
    				Reverse(l, tot);
    			if (op == 'G')
    				Query(l, tot);
    		}
    	}
    	return 0;
    }
    /*
    9 14
    2 -6 3 5 1 -5 -3 6 3
    GET-SUM 5 4
    MAX-SUM
    INSERT 8 3 -5 7 2
    GET-SUM 8 4
    MAX-SUM
    DELETE 12 1
    GET-SUM 8 4
    MAX-SUM
    MAKE-SAME 3 3 2
    GET-SUM 5 4
    MAX-SUM
    REVERSE 3 6
    GET-SUM 5 4
    MAX-SUM
    */



  • 相关阅读:
    Spring AOP概念理解 (通俗易懂)
    分享一下几个关于ssm及spring原理的专栏链接
    liux高级常用命令
    Linux基础常用命令
    SP1716 GSS3
    HDU6579 Operation
    CF1205C Palindromic Paths
    CF1213G Path Queries
    CF1213F Unstable String Sort
    CF1213E Two Small Strings
  • 原文地址:https://www.cnblogs.com/cocottt/p/6765021.html
Copyright © 2011-2022 走看看