• [bzoj 1251]序列终结者


    传送门

    Description

    网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。

    Solution

    疯狂水模板题……
    还是wa了几次,这次是因为build的时候左孩子(l,mid-1)写成了(l,mid)
    我真的不行


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    class FHQ
    {
    	#define MN 50005
    	private:
    		int ls[MN],rs[MN],add[MN],V[MN],ans[MN],pri[MN],siz[MN],sz;
    		bool rev[MN];
    		inline unsigned int random()
    		{
    			static int x=23333;
    			return x^=x<<13,x^=x>>17,x^=x<<5;
    		}
    		inline void up(int x)
    		{
    			siz[x]=siz[ls[x]]+siz[rs[x]]+1;
    			ans[x]=V[x];
    			if(ls[x]) ans[x]=max(ans[x],ans[ls[x]]);
    			if(rs[x]) ans[x]=max(ans[x],ans[rs[x]]);
    		}
    		inline void down(int x)
    		{
    			if(add[x])
    			{
    				if(ls[x])
    				{
    					ans[ls[x]]+=add[x];V[ls[x]]+=add[x];
    					add[ls[x]]+=add[x];
    				}
    				if(rs[x])
    				{
    					ans[rs[x]]+=add[x];V[rs[x]]+=add[x];
    					add[rs[x]]+=add[x];
    				}
    				add[x]=0;
    			}
    			if(rev[x])
    			{
    				std::swap(ls[x],rs[x]);
    				if(ls[x]) rev[ls[x]]^=1;
    				if(rs[x]) rev[rs[x]]^=1;
    				rev[x]=0; 
    			}
    		}
    	public:
    		int rt;
    		int Merge(int rt1,int rt2)
    		{
    			if(rt1) down(rt1);
    			if(rt2) down(rt2);
    			if(!rt1||!rt2) return rt1|rt2;
    			if(pri[rt1]<pri[rt2])
    			{
    				rs[rt1]=Merge(rs[rt1],rt2);
    				up(rt1);return rt1;
    			}
    			else
    			{
    				ls[rt2]=Merge(rt1,ls[rt2]);
    				up(rt2);return rt2;
    			}
    		}
    		void Split(int x,int k,int& rt1,int& rt2)
    		{
    			if(!x) return (void)(rt1=rt2=0);
    			down(x);
    			if(siz[ls[x]]>=k)
    			{
    				Split(ls[x],k,rt1,rt2);
    				ls[x]=rt2,rt2=x,up(rt2);
    			}
    			else
    			{
    				Split(rs[x],k-siz[ls[x]]-1,rt1,rt2);
    				rs[x]=rt1,rt1=x,up(rt1);
    			}
    		}
    		void Build(int &x,int l,int r)
    		{
    			if(l>r) return;
    			x=++sz;int mid=(l+r)>>1;
    			V[x]=rev[x]=add[x]=ans[x]=0;pri[x]=random();
    			if(l==r) return(void)(siz[x]=1);
    			Build(ls[x],l,mid-1);Build(rs[x],mid+1,r);up(x);
    		}
    		void Add(int l,int r,int c)
    		{
    			register int rt1,rt2,rt3,rt4;
    			Split(rt,l-1,rt1,rt2);Split(rt2,r-l+1,rt3,rt4);
    			add[rt3]+=c;V[rt3]+=c;ans[rt3]+=c;rt=Merge(rt1,Merge(rt3,rt4));
    		}
    		void Reverse(int l,int r)
    		{
    			register int rt1,rt2,rt3,rt4;
    			Split(rt,l-1,rt1,rt2);Split(rt2,r-l+1,rt3,rt4);
    			rev[rt3]^=1;rt=Merge(rt1,Merge(rt3,rt4));
    		}
    		void QueMax(int l,int r)
    		{
    			register int rt1,rt2,rt3,rt4;
    			Split(rt,l-1,rt1,rt2);Split(rt2,r-l+1,rt3,rt4);
    			printf("%d
    ",ans[rt3]),rt=Merge(rt1,Merge(rt3,rt4));
    		}
    	#undef MN
    }T;
    int main()
    {
    	register int n,m,k,l,r;
    	n=read();m=read();
    	T.Build(T.rt,1,n);
    	while(m--)
    	{
    		k=read(),l=read(),r=read();
    		if(k==1) T.Add(l,r,read());
    		else if(k==2) T.Reverse(l,r);
    		else if(k==3) T.QueMax(l,r); 
    	}
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    二分查找
    合并两个或多个有序链表
    前缀和
    田忌赛马
    小根堆实现
    汉化破解:ASPack 2.12 &gt; Alexey Solodovnikov Dump
    EXT是一款强大的AJAX框架
    var TempViewPanel = Ext
    【Azure 事件中心】如何查看事件中心的消息中具体报文内容呢?
    【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表达式? triggerBody()?
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10162110.html
Copyright © 2020-2023  润新知