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

    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

    HINT


    splay操作大合集啊。。。这题过了splay基本操作也差不多毕业了。插入操作记得不能插入链,要递归建树插入;删除的话要记得写个回收站,不然空间会炸;区间操作打个标记就好;区间求和记个sum数组就好;区间最大连续子串和,首先我们可以参考线段树的区间最大连续和,但是线段树和splay有点区别,因此我们只需要做点小(da)小(da)的改动即可

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x>=10)     print(x/10);
    	putchar(x%10+'0');
    }
    const int N=5e5;
    int stack[N+10],top,v[N+10];
    struct Splay{
    	#define T(x) (tree[f[x]][1]==x)
    	#define ls(x) tree[x][0]
    	#define rs(x) tree[x][1]
    	int tree[N+10][2],f[N+10],size[N+10],val[N+10];
    	int sum[N+10],L[N+10],R[N+10],Max[N+10];
    	bool rev[N+10],mark[N+10];
    	int root,len;
    	void cov_tag(int x,int v){
    		if (!x)	return;
    		sum[x]=size[x]*v;
    		val[x]=v;
    		L[x]=R[x]=Max[x]=max(v,sum[x]);
    		mark[x]=1,rev[x]=0;
    	}
    	void rev_tag(int x){
    		if (!x)	return;
    		swap(L[x],R[x]);
    		swap(ls(x),rs(x));
    		rev[x]^=1;
    	}
    	void pushdown(int x){
    		if (rev[x]){
    			rev_tag(ls(x));
    			rev_tag(rs(x));
    			rev[x]=0;
    		}
    		if (mark[x]){
    			cov_tag(ls(x),val[x]),
    			cov_tag(rs(x),val[x]);
    			mark[x]=0;
    		}
    	}
    	void updata(int x){
    		size[x]=size[ls(x)]+size[rs(x)]+1;
    		Max[x]=max(max(Max[ls(x)],Max[rs(x)]),max(0,R[ls(x)])+val[x]+max(0,L[rs(x)]));
    		L[x]=max(L[ls(x)],sum[ls(x)]+val[x]+max(0,L[rs(x)]));
    		R[x]=max(R[rs(x)],sum[rs(x)]+val[x]+max(0,R[ls(x)]));
    		sum[x]=sum[ls(x)]+sum[rs(x)]+val[x];
    	}
    	int get(){
    		int x;
    		x=top?stack[top--]:++len;
    		ls(x)=rs(x)=f[x]=0;
    		rev[x]=mark[x]=0;
    		size[x]=1;
    		sum[x]=L[x]=R[x]=val[x]=-1e9;
    		return x;
    	}
    	void build(int fa,int l,int r,int &x){
    		if (l>r)	return;
    		int mid=(l+r)>>1;
    		x=get(),f[x]=fa,val[x]=v[mid];
    		if (l==r){
    			size[x]=1;
    			Max[x]=L[x]=R[x]=sum[x]=val[x];
    			return;
    		}
    		build(x,l,mid-1,ls(x)),
    		build(x,mid+1,r,rs(x));
    		updata(x);
    	}
    	void init(int n){
    		L[0]=R[0]=Max[0]=-1e9;
    		len=2,root=1;
    		rs(1)=size[1]=2,L[1]=R[1]=val[1]=sum[1]=-1e9;
    		f[2] =size[2]=1,L[2]=R[2]=val[2]=sum[2]=-1e9;
    		for (int i=1;i<=n;i++)	v[i]=read();
    		build(2,1,n,ls(2));
    		updata(2),updata(1);
    	}
    	void move(int x){
    		int fa=f[x],son=tree[x][T(x)^1];
    		tree[x][T(x)^1]=fa;
    		tree[fa][T(x)]=son;
    		if (son)	f[son]=fa;
    		f[x]=f[fa];
    		if (f[x])	tree[f[x]][T(fa)]=x;
    		f[fa]=x;
    		updata(fa),updata(x);
    	}
    	void splay(int x){
    		while (f[x]){
    			if (f[f[x]])	T(x)==T(f[x])?move(f[x]):move(x);
    			move(x);
    		}
    		root=x;
    	}
    	int find(int x,int i){
    		pushdown(i);
    		if (size[ls(i)]+1==x)	return i;
    		if (x<=size[ls(i)])	return find(x,ls(i));
    		return find(x-size[ls(i)]-1,rs(i));
    	}
    	void insert(){
    		int x=read()+1,y=x+1,tot=read();
    		x=find(x,root),splay(x);
    		y=find(y,root),splay(y);
    		if (f[x]!=root)	move(x);
    		for (int i=1;i<=tot;i++)	v[i]=read();
    		build(x,1,tot,rs(x));
    		updata(x),updata(y);
    	}
    	void reuse(int x){
    		if (!x)	return;
    		stack[++top]=x;
    		reuse(ls(x)),reuse(rs(x));
    	}
    	void Del(){
    		int x=read(),y=read()+x-1;
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		reuse(rs(x));
    		f[rs(x)]=0,rs(x)=0;
    		updata(x),updata(y);
    	}
    	void cover(){
    		int x=read(),y=read()+x-1,v=read();
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		cov_tag(rs(x),v);
    		updata(x),updata(y);
    	}
    	void reverse(){
    		int x=read(),y=read()+x-1;
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		rev_tag(rs(x));
    		updata(x),updata(y);
    	}
    	void query_sum(){
    		int x=read(),y=read()+x-1;
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		printf("%d
    ",sum[rs(x)]);
    	}
    	void query_max(){printf("%d
    ",Max[root]);}
    }T;
    char s[10];
    int main(){
    	int n=read(),m=read();
    	T.init(n);
    	for (int i=1;i<=m;i++){
    		scanf("%s",s);
    		//第3位都不一样,我懒
    		if (s[2]=='L')	T.Del();
    		if (s[2]=='K')	T.cover();
    		if (s[2]=='S')	T.insert();
    		if (s[2]=='V')	T.reverse();
    		if (s[2]=='T')	T.query_sum();
    		if (s[2]=='X')	T.query_max();
    	}
    	return 0;
    }
    
  • 相关阅读:
    HDU1506 Largest Rectangle in a Histogram(算竞进阶习题)
    洛谷P1073 最优贸易
    CH2101 可达性统计(算竞进阶习题)
    BZOJ1012 最大数maxnumber
    POJ 3764 The XOR Longest Path
    洛谷P4513 小白逛公园
    外边距叠加问题
    读JS高性能总结——DOM编程(一)
    DOM修改元素的方法总结
    DOM查找元素的方法总结
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/9480049.html
Copyright © 2011-2022 走看看