zoukankan      html  css  js  c++  java
  • 【洛谷P2710】数列

    题目

    题目链接:https://www.luogu.com.cn/problem/P2710
    维护一个数列,共 \(7\) 种操作:

    I. INSERT x n a1 a2 .. an 在第 \(x\) 个数后插入 \(n\) 个数分别为 \(a_1\dots a_n\)

    II. DELETE x n 删除第 \(x\) 个数开始的 \(n\) 个数。

    III. REVERSE x n 翻转第 \(x\) 个数开始的 \(n\) 个数的区间。

    IV. MAKE-SAME x n t 将第 \(x\) 个数开始的 \(n\) 个数统一改为 \(t\)

    V. GET-SUM x n 输出第 \(x\) 个数开始的 \(n\) 个数的和。

    VI. GET x 输出第 \(x\) 个数的值。

    VII. MAX-SUM x n 输出第 \(x\) 个数开始的 \(n\) 个数的最大连续子序列和。

    思路

    很明显可以用 Splay。然后这道毒瘤题调了我至少八九小时 /kk。
    主要原因还是对 Splay 不熟。其实做这道题主要目的也是练习 Splay。

    代码长度一度达到 5kb /fad。


    操作一、二、三、五、六都是 Spaly 的基本操作。
    对于区间推平,我们在每一个区间维护一个推平标记,下次递归到子树的时候再下传标记。
    对于区间最大子段和,维护区间最大前缀和,区间最大后缀和即可。转移的时候可以通过这两项来计算出区间最大子段和。
    然后就没什么好说的了。这道题主要考察的不是算法,而是心态。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=500010,Inf=1e9;
    int n,m,rt,last;
    char type[10];
    
    struct Splay
    {
    	int tot,ch[N][2],lazy[N],size[N],val[N],fa[N],sum[N],lmax[N],rmax[N],smax[N],filp[N];
    	
    	Splay()
    	{
    		memset(lazy,0x3f3f3f3f,sizeof(lazy));
    		memset(smax,0xcf,sizeof(smax));
    	}
    	
    	int pos(int x)
    	{
    		return ch[fa[x]][1]==x;
    	}
    	
    	void pushup(int x)
    	{
    		int lc=ch[x][0],rc=ch[x][1];
    		sum[x]=sum[lc]+sum[rc]+val[x];
    		size[x]=size[lc]+size[rc]+1;
    		lmax[x]=max(lmax[lc],sum[lc]+val[x]+lmax[rc]);
    		rmax[x]=max(rmax[rc],sum[rc]+val[x]+rmax[lc]);
    		smax[x]=max(max(smax[lc],smax[rc]),rmax[lc]+val[x]+lmax[rc]);
    	}
    	
    	void pushdown(int x)
    	{
    		int lc=ch[x][0],rc=ch[x][1];
    		if (lazy[x]!=0x3f3f3f3f)
    		{
    			if (lc)
    			{
    				val[lc]=lazy[lc]=lazy[x];
    				sum[lc]=lazy[x]*size[lc];
    				lmax[lc]=rmax[lc]=max(lazy[x],0)*size[lc];
    				smax[lc]=max(lazy[x],0)*(size[lc]-1)+lazy[x];
    			}
    			if (rc)
    			{
    				val[rc]=lazy[rc]=lazy[x];
    				sum[rc]=lazy[x]*size[rc];
    				lmax[rc]=rmax[rc]=max(lazy[x],0)*size[rc];
    				smax[rc]=max(lazy[x],0)*(size[rc]-1)+lazy[x];
    			}
    			lazy[x]=0x3f3f3f3f;
    		}
    		if (filp[x])
    		{
    			filp[lc]^=1; filp[rc]^=1; filp[x]=0;
    			swap(ch[lc][0],ch[lc][1]),swap(lmax[lc],rmax[lc]);
    			swap(ch[rc][0],ch[rc][1]),swap(lmax[rc],rmax[rc]);
    		}
    	}
    	
    	void build()
    	{
    		tot++;
    		val[tot]=sum[tot]=-Inf; size[tot]=1;
    		lmax[tot]=rmax[tot]=0; smax[tot]=-Inf;
    		tot++;
    		val[tot]=sum[tot]=Inf; size[tot]=1;
    		lmax[tot]=rmax[tot]=smax[tot]=Inf;
    		ch[1][1]=2; fa[2]=rt=1;
    		pushup(2); pushup(1);
    	}
    	
    	void rotate(int x)
    	{
    		int y=fa[x],z=fa[y],k=pos(x),c=ch[x][k^1];
    		pushdown(x);
    		fa[x]=z; ch[z][pos(y)]=x;
    		fa[y]=x; ch[x][k^1]=y;
    		fa[c]=y; ch[y][k]=c;
    		pushup(y); pushup(x);
    	}
    	
    	void splay(int x,int f=0)
    	{
    		while (fa[x]!=f)
    		{
    			int y=fa[x],z=fa[y];
    			if (z==f) rotate(x);
    			else if (pos(x)==pos(y)) rotate(y),rotate(x);
    			else rotate(x),rotate(x);
    		}
    		if (!f) rt=x;
    	}
    	
    	void ins(int x,int v)
    	{
    		int p=rt,f=0,k=0;
    		while (p)
    		{
    			pushdown(p); f=p;
    			if (size[ch[p][0]]>=x) p=ch[p][0],k=0;
    				else x-=(size[ch[p][0]]+1),p=ch[p][1],k=1;
    		}
    		fa[++tot]=f; 
    		val[tot]=sum[tot]=v; size[tot]=1;
    		lmax[tot]=rmax[tot]=max(v,0); smax[tot]=v;
    		if (f) ch[f][k]=tot;
    			else rt=tot;
    		pushup(tot); pushup(f);
    		splay(tot);
    	}
    	
    	int find(int k)
    	{
    		int p=rt;
    		while (k)
    		{
    			pushdown(p);
    			if (k==size[ch[p][0]]+1) break;
    			if (k<=size[ch[p][0]]) p=ch[p][0];
    				else k-=(size[ch[p][0]]+1),p=ch[p][1];
    		}
    		splay(p);
    		return p;
    	}
    	
    	void del(int l,int r)
    	{
    		int x=find(l-1),y=find(r+1);
    		splay(x); splay(y,rt);
    		ch[y][0]=0;
    		pushup(y); pushup(x);
    	}
    	
    	void rev(int l,int r)
    	{
    		int x=find(l-1),y=find(r+1);
    		splay(x); splay(y,rt);
    		x=ch[y][0]; filp[x]^=1;
    		swap(ch[x][0],ch[x][1]); 
    		swap(lmax[x],rmax[x]);
    		pushup(y); pushup(fa[y]);
    	}
    	
    	void update(int l,int r,int v)
    	{
    		int x=find(l-1),y=find(r+1);
    		splay(x); splay(y,rt);
    		x=ch[y][0];
    		lazy[x]=val[x]=v; sum[x]=v*size[x];
    		lmax[x]=rmax[x]=max(v,0)*size[x];
    		smax[x]=max(v,0)*(size[x]-1)+v;
    		pushup(y); pushup(fa[y]);
    	}
    	
    	int querysum(int l,int r)
    	{
    		int x=find(l-1),y=find(r+1);
    		splay(x); splay(y,rt);
    		return sum[ch[y][0]];
    	}
    	
    	int querymax(int l,int r)
    	{
    		int x=find(l-1),y=find(r+1);
    		splay(x); splay(y,rt);
    		return smax[ch[y][0]];
    	}
    }splay;
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	splay.build();
    	for (int i=1,x;i<=n;i++)
    	{
    		scanf("%d",&x);
    		splay.ins(i,x);
    	}
    	for (int i=1,x,k,t;i<=m;i++)
    	{
    		for (int i=0;i<=9;i++) type[i]=' ';
    		scanf("%s",type);
    		if (type[0]=='I')
    		{
    			scanf("%d%d",&x,&k);
    			for (int j=1;j<=k;j++)
    			{
    				scanf("%d",&t);
    				splay.ins(x+j,t);
    			}
    		}
    		else if (type[0]=='D')
    		{
    			scanf("%d%d",&x,&k);
    			splay.del(x+1,x+k);
    		}
    		else if (type[0]=='R')
    		{
    			scanf("%d%d",&x,&k);
    			splay.rev(x+1,x+k);
    		}
    		else if (type[0]=='M' && type[2]=='K')
    		{
    			scanf("%d%d%d",&x,&k,&t);
    			splay.update(x+1,x+k,t);
    		}
    		else if (type[0]=='G' && type[4]=='S')
    		{
    			scanf("%d%d",&x,&k);
    			printf("%d\n",last=splay.querysum(x+1,x+k));
    		}
    		else if (type[0]=='G')
    		{
    			scanf("%d",&x);
    			printf("%d\n",last=splay.querysum(x+1,x+1));
    		}
    		else if (type[0]=='M' && type[2]=='X')
    		{
    			scanf("%d%d",&x,&k);
    			printf("%d\n",last=splay.querymax(x+1,x+k));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    PHP开发APP接口(三)
    PHP开发APP接口(二)
    PHP开发APP接口(一)
    解密PHP模糊查询技术
    流程的问题
    德邦项目《表》
    微信公众号开发1
    在world2013中插入GB_2312
    HTML5笔记(一)
    蓝色文字显示
  • 原文地址:https://www.cnblogs.com/stoorz/p/13783920.html
Copyright © 2011-2022 走看看