zoukankan      html  css  js  c++  java
  • bzoj 1500 维修序列

    Written with StackEdit.

    Description

    请写一个程序,要求维护一个数列,支持以下 (6) 种操作:
    请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格

    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

    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

    Sample Output

    -1
    10
    1
    10

    Solution

    • 大数据结构题...敲完这道题保证神清气爽...
    • 本蒟蒻的做法是用一棵非旋(treap)维护这个数列.
    • (split)时按照(size)分割.这样分割出的区间是以下标排序的.
      • (insert):将给的数中序遍历,建成一棵小树后,再插入整颗树中.这样个人感性理解会比较方便.初始化也可以这样做.
      • (delete):将给的区间(split)出来,合并两旁的树.注意开内存栈回收空间.
      • (make-same):将给的区间(split)出来,打上对应的标记.
      • (reverse):将给的区间(split)出来,打上对应的标记.
      • (getsum):将给的区间(split)出来,直接返回(pushup)时维护的对应答案.
      • (maxsum):直接返回整颗树根节点(pushup)时维护的对应答案.
    • 这道题的细节部分主要在(pushup)函数内,而因为此题中最大子段和要求选出的子段不为空(题面没说清,根据数据感性理解的),所以初始化虚拟节点(0)的时候也是比较讲究的.具体可以看下面的代码.
    • 所以我为啥还要去学Splay呢.
    #include<bits/stdc++.h>
    #define inf 1e9
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int MAXN=5e5+10;
    struct FhqTreap
    {
    	int x,y,z,p,q;
    	int idx;
    	int stk[MAXN],top;
    	int w[MAXN];
    	int root;
    	struct node{
    		int lson,rson,siz,key,weight;
    		int rev,cov;//reverse and cover
    		int sum,mx;//总和,最大子段和
    		int lm,rm;//从左/右边开始的最大子段和 
    	}treap[MAXN];
    	FhqTreap()
    		{
    			idx=0;
    			top=0;
    			root=0;
    			top=0;
    			treap[0].sum=0;
    			treap[0].siz=0;
    			treap[0].mx=-inf;//特别注意.否则pushup最大子段和的时候,可能会出现空的子段. 
    			treap[0].lm=0;
    			treap[0].rm=0;
    			treap[0].rev=0;
    			treap[0].cov=inf;
    		}
    	#define rt treap[o]
    	#define ls treap[treap[o].lson]
    	#define rs treap[treap[o].rson]
    	inline int newnode(int key)
    		{
    			int o=top?stk[top--]:++idx;
    			rt.lson=rt.rson=0;
    			rt.siz=1;
    			rt.key=key;
    			rt.weight=rand();
    			rt.rev=0;
    			rt.cov=inf;
    			rt.sum=key;
    			rt.mx=key;
    			rt.lm=key;
    			rt.rm=key;
    			return o;
    		}
    	void pushup(int o)
    		{
    			if(!o)
    				return;
    			rt.siz=ls.siz+rs.siz+1;
    			rt.sum=ls.sum+rs.sum+rt.key;
    			rt.lm=rt.key;
    			rt.lm=max(ls.lm,max(ls.sum+rt.key,ls.sum+rt.key+rs.lm));
    			rt.rm=rt.key;
    			rt.rm=max(rs.rm,max(rs.sum+rt.key,rs.sum+rt.key+ls.rm));
    			rt.mx=rt.key;
    			rt.mx=max((ls.rm>0?ls.rm:0)+rt.key+(rs.lm>0?rs.lm:0),max(ls.mx,rs.mx));//若子节点不存在,mx赋为-inf,强制选择了rt,保证不为空. 
    		}
    	void upend(int o)
    		{
    			swap(rt.lson,rt.rson);
    			swap(rt.lm,rt.rm);
    			rt.rev^=1;	
    		}
    	void cover(int o,int val)
    		{
    			rt.key=val;
    			rt.sum=rt.siz*val;
    			rt.mx=max(rt.sum,val);//字段长度至少为1
    			rt.lm=max(rt.sum,0);// remained to be updated
    			rt.rm=max(rt.sum,0); 
    			rt.cov=val;
    		}
    	void pushdown(int o)
    		{
    			if(rt.rev)
    				{
    					if(rt.lson)
    						upend(rt.lson);
    					if(rt.rson)
    						upend(rt.rson);
    				}
    			if(rt.cov!=inf)
    				{
    					if(rt.lson)
    						cover(rt.lson,rt.cov);
    					if(rt.rson)
    						cover(rt.rson,rt.cov);
    				}
    			rt.rev=0;
    			rt.cov=inf;
    		}
    	void recover(int o)
    		{
    			if(!o)
    				return;
    			stk[++top]=o;
    			recover(rt.lson);
    			recover(rt.rson);
    		}
    	void split(int &x,int &y,int k,int o)//按子树大小分,前k个分到x中,其余y中 
    		{
    			if(!o)
    				x=y=0;
    			else
    				{
    					pushdown(o);
    					if(k<=ls.siz)
    						{
    							y=o;
    							split(x,rt.lson,k,rt.lson);
    						}
    					else
    						{
    							x=o;
    							split(rt.rson,y,k-ls.siz-1,rt.rson);
    						}
    					pushup(o);
    				}
    		}
    	int merge(int x,int y)
    		{
    			if(x==0 || y==0)
    				return x+y;
    			pushdown(x);
    			pushdown(y);
    			if(treap[x].weight<treap[y].weight)
    				{
    					treap[x].rson=merge(treap[x].rson,y);
    					pushup(x);
    					return x;
    				}
    			else
    				{
    					treap[y].lson=merge(x,treap[y].lson);
    					pushup(y);
    					return y;
    				}
    		}
    	int BuildTree(int l,int r)//以w[l]~w[r]建树,返回树根标号 
    		{
    			if(l>r)
    				return 0;
    			int mid=(l+r)>>1;
    			int o=newnode(w[mid]);
    			rt.lson=BuildTree(l,mid-1);
    			rt.rson=BuildTree(mid+1,r);
    			pushup(o);
    			return o;
    		}
    	int getdata(int tot)
    		{
    			for(int i=1;i<=tot;++i)
    				w[i]=read();
    			return BuildTree(1,tot);
    		}
    	void ins(int pos,int tot)
    		{
    			int o=getdata(tot);
    			split(x,y,pos,root);
    			x=merge(x,o);
    			root=merge(x,y);
    		}
    	void del(int pos,int tot)
    		{
    			split(x,y,pos-1,root);
    			split(p,q,tot,y);
    			root=merge(x,q);
    			recover(p);
    		}
    	void update(int pos,int tot,int c)
    		{
    			split(x,y,pos-1,root);
    			split(p,q,tot,y);
    			cover(p,c);
    			root=merge(x,merge(p,q));
    		}
    	void rev(int pos,int tot)
    		{
    			split(x,y,pos-1,root);
    			split(p,q,tot,y);
    			upend(p);
    			root=merge(x,merge(p,q));
    		}
    	int getsum(int pos,int tot)
    		{
    			split(x,y,pos-1,root);
    			split(p,q,tot,y);
    			int res=treap[p].sum;
    			root=merge(x,merge(p,q));
    			return res;
    		}
    	int maxsum()
    		{
    			return treap[root].mx;
    		}
    	void pr(int o)
    		{
    			if(!o)
    				return;
    			pr(rt.lson);
    			printf("%d ",rt.key);
    			pr(rt.rson);
    		}
    	void print()
    		{
    			pr(root);
    			puts("");
    		}
    }T;
    int n,m;
    int main()
    {
    	srand(time(NULL));
    	n=read(),m=read();
    	T.ins(0,n);
    //	T.print();
    	char op[50];
    	int pos,tot,c;
    	for(int i=1;i<=m;++i)
    		{
    			scanf("%s",op);
    			if(op[0]=='I')
    				{
    					pos=read();
    					tot=read();
    					T.ins(pos,tot);
    				}
    			else if(op[0]=='D')
    				{
    					pos=read();
    					tot=read();
    					T.del(pos,tot);
    				}
    			else if(op[0]=='M' && op[2]=='K')
    				{
    					pos=read();
    					tot=read();
    					c=read();
    					T.update(pos,tot,c);
    				}
    			else if(op[0]=='R')
    				{
    					pos=read();
    					tot=read();
    					T.rev(pos,tot);
    				}
    			else if(op[0]=='G')
    				{
    					pos=read();
    					tot=read();
    					int ans=T.getsum(pos,tot);
    					printf("%d
    ",ans);
    				}
    			else if(op[0]=='M' && op[2]=='X')
    				{
    					int ans=T.maxsum();
    					printf("%d
    ",ans);
    				}
    		}
    	return 0;
    }
    
  • 相关阅读:
    Flex 自定义事件
    ORACLE中date类型字段的处理
    微信公众号开发
    idHTTP最简洁的修改和取得Cookie例子
    使用TidCookieManager得到cookie
    dhttp与IdCookieManager处理登陆过程
    Delphi IdHTTP 设置cookie 和访问后读取Cookie 值(重要collection不需要item索引)
    idhttp与cookie
    delphi inttohex 整型到十六进制
    03006_Servlet简介
  • 原文地址:https://www.cnblogs.com/jklover/p/10110950.html
Copyright © 2011-2022 走看看