• 【bzoj1500】[NOI2005]维修数列 Splay


    题目描述

    输入

    输入的第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


    题解

    做了4小时的Splay“裸题”。

    大概就是各种细节处理一下就行了。

    这里ls和rs的数的个数可以为0,但ts的数的个数一定大于0,应该可以在代码中pushup部分理解。

    ts[0]要赋成极小值,否则pushup时可能会因使用到0节点而不为真正值。

    当某数为负数时,ls和rs为0,但是ts为v,即小于0。这点在pushdown中尤其突出。

    pushdown中有无儿子的问题,一定要判断。

    不能开特大空间,所以需要循环利用下标,把能用的下标存到一个队列中,加入时取出队首,删除时加到队尾。

    搞定细节以后(话说不是先敲大体在搞细节吗),就是splay裸题。

    220行丑丑的代码。。

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define N 600010
    using namespace std;
    int sum[N] , v[N] , ls[N] , rs[N] , ts[N] , si[N] , rev[N] , tag[N] , c[2][N] , fa[N] , root;
    char str[20];
    queue<int> q;
    inline int read()
    {
    	int num = 0 , f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-')f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') num = (num << 3) + (num << 1) + ch - '0' , ch = getchar();
    	return num * f;
    }
    void pushup(int k)
    {
    	int l = c[0][k] , r = c[1][k];
    	sum[k] = sum[l] + sum[r] + v[k];
    	ls[k] = max(ls[l] , sum[l] + v[k] + ls[r]);
    	rs[k] = max(rs[r] , sum[r] + v[k] + rs[l]);
    	ts[k] = max(max(ts[l] , ts[r]) , rs[l] + v[k] + ls[r]);
    	si[k] = si[l] + si[r] + 1;
    }
    void pushdown(int k)
    {
    	int l = c[0][k] , r = c[1][k];
    	if(tag[k] != 0x3f3f3f3f)
    	{
    		if(l) sum[l] = si[l] * tag[k] , v[l] = tag[l] = tag[k];
    		if(r) sum[r] = si[r] * tag[k] , v[r] = tag[r] = tag[k];
    		if(tag[k] > 0)
    		{
    			if(l) ls[l] = rs[l] = ts[l] = si[l] * tag[k];
    			if(r) ls[r] = rs[r] = ts[r] = si[r] * tag[k];
    		}
    		else
    		{
    			if(l) ls[l] = rs[l] = 0 , ts[l] = tag[k];
    			if(r) ls[r] = rs[r] = 0 , ts[r] = tag[k];
    		}
    		tag[k] = 0x3f3f3f3f;
    	}
    	if(rev[k])
    	{
    		swap(c[0][l] , c[1][l]);
    		swap(c[0][r] , c[1][r]);
    		swap(ls[l] , rs[l]);
    		swap(ls[r] , rs[r]);
    		rev[l] ^= 1;
    		rev[r] ^= 1;
    		rev[k] = 0;
    	}
    }
    void build(int l , int r , int f)
    {
    	if(l > r) return;
    	int mid = (l + r) >> 1;
    	build(l , mid - 1 , mid);
    	build(mid + 1 , r , mid);
    	fa[mid] = f;
    	c[mid > f][f] = mid;
    	pushup(mid);
    }
    void rotate(int &k , int x)
    {
    	int y = fa[x] , z = fa[y] , l , r;
    	l = (c[0][y] != x);
    	r = l ^ 1;
    	if(y == k) k = x;
    	else if(c[0][z] == y) c[0][z] = x;
    	else c[1][z] = x;
    	fa[x] = z;
    	fa[y] = x;
    	fa[c[r][x]] = y;
    	c[l][y] = c[r][x];
    	c[r][x] = y;
    	pushup(y);
    	pushup(x);
    }
    void splay(int &k , int x)
    {
    	while(k != x)
    	{
    		int y = fa[x] , z = fa[y];
    		if(y != k)
    		{
    			if(c[0][z] == y ^ c[0][y] == x) rotate(k , x);
    			else rotate(k , y);
    		}
    		rotate(k , x);
    	}
    }
    int find(int k , int x)
    {
    	pushdown(k);
    	if(x <= si[c[0][k]]) return find(c[0][k] , x);
    	else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
    	else return k;
    }
    void update(int l , int r , int x)
    {
    	int ta , tb , t;
    	ta = find(root , l - 1);
    	splay(root , ta);
    	tb = find(root , r + 1);
    	splay(c[1][root] , tb);
    	t = c[0][c[1][root]];
    	sum[t] = si[t] * x;
    	if(x > 0) ls[t] = rs[t] = ts[t] = si[t] * x;
    	else ls[t] = rs[t] = 0 , ts[t] = x;
    	v[t] = tag[t] = x;
    	pushup(c[1][root]);
    	pushup(root);
    }
    void rever(int l , int r)
    {
    	int ta , tb , t;
    	ta = find(root , l - 1);
    	splay(root , ta);
    	tb = find(root , r + 1);
    	splay(c[1][root] , tb);
    	t = c[0][c[1][root]];
    	swap(c[0][t] , c[1][t]);
    	swap(ls[t] , rs[t]);
    	rev[t] ^= 1;
    }
    void cls(int k)
    {
    	if(k)
    	{
    		int l = c[0][k] , r = c[1][k];
    		cls(l) , q.push(k) , cls(r);
    		tag[k] = 0x3f3f3f3f;
    		rev[k] = sum[k] = si[k] = ls[k] = rs[k] = ts[k] = c[0][k] = c[1][k] = fa[k] = 0;
    	}
    }
    int main()
    {
    	int n , m , i , p , t , x , ta , tb , id;
    	n = read() , m = read();
    	for(i = 2 ; i <= n + 1 ; i ++ )
    		v[i] = read();
    	memset(tag , 0x3f , sizeof(tag));
    	ts[0] = 0xc0000000;
    	build(1 , n + 2 , 0);
    	root = (n + 3) >> 1;
    	for(i = n + 3 ; i <= 600005 ; i ++ ) q.push(i);
    	while(m -- )
    	{
    		scanf("%s" , str);
    		switch(str[2])
    		{
    			case 'S':
    			{
    				p = read() , t = read();
    				for(i = 1 ; i <= t ; i ++ )
    				{
    					ta = find(root , p + i);
    					splay(root , ta);
    					tb = find(root , p + i + 1);
    					splay(c[1][root] , tb);
    					x = read();
    					id = q.front() , q.pop();
    					v[id] = x;
    					fa[id] = c[1][root];
    					c[0][c[1][root]] = id;
    					pushup(c[0][c[1][root]]);
    					pushup(c[1][root]);
    					pushup(root);
    				}
    				break;
    			}
    			case 'L':
    			{
    				p = read() , t = read();
    				ta = find(root , p);
    				splay(root , ta);
    				tb = find(root , p + t + 1);
    				splay(c[1][root] , tb);
    				cls(c[0][c[1][root]]);
    				c[0][c[1][root]] = 0;
    				pushup(c[1][root]);
    				pushup(root);
    				break;
    			}
    			case 'K':
    			{
    				p = read() , t = read() , x = read();
    				update(p + 1 , p + t , x);
    				break;
    			}
    			case 'V':
    			{
    				p = read() , t = read();
    				rever(p + 1 , p + t);
    				break;
    			}
    			case 'T':
    			{
    				p = read() , t = read();
    				ta = find(root , p);
    				splay(root , ta);
    				tb = find(root , p + t + 1);
    				splay(c[1][root] , tb);
    				printf("%d
    " , sum[c[0][c[1][root]]]);
    				break;
    			}
    			default:
    			{
    				ta = find(root , 1);
    				splay(root , ta);
    				tb = find(root , si[root]);
    				splay(c[1][root] , tb);
    				printf("%d
    " , ts[c[0][c[1][root]]]);
    			}
    		}
    	}
    	return 0;
    }

     

  • 相关阅读:
    python入门1
    查找字段 和查找组件
    DBGRID 拖动滚动条 和 鼠标滚轮的问题
    数据集 过滤时 RecordCount 属性
    查找字段 如何 过滤
    数据集控件 放在 数据模块 上后,如何写事件代码
    取TTable 过滤后的记录数
    判断 Windows操作系统是32位还是64位
    MatchText MatchStr 区别
    EClassNotFound
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6440155.html
Copyright © 2020-2023  润新知