zoukankan      html  css  js  c++  java
  • test20180919 选择客栈

    题意


    分析

    不难发现把增加人数看成减少人数,上限是w 看成总数是w,问题就变成了询问有多少个子区间没有0。

    考虑这个问题困难在哪里,就是区间加减法让我们不好判断0 的位置。
    因为题目保证每个位置的值非负,所以实际上我们只需要对于每个区间维护不包含其最小值的子区间的个数。
    于是用线段树来维护,每个节点维护区间左边开始第一次出现最小值的位置(到左端的长度),右边开始第一次出现最小值的位置(到右端的长度),最小值的值,区间长度,以及有多少个子区间不包含其最小值即可。
    合并的话,分类讨论最小值在哪个区间,然后用上述信息就可以完成合并了。
    复杂度为(O(n +m log n))

    代码

    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<ctime>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<list>
    #include<deque>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<bitset>
    #include<algorithm>
    #include<complex>
    #pragma GCC optimize ("O0")
    using namespace std;
    template<class T> inline T read(T&x)
    {
        T data=0;
    	int w=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
    		if(ch=='-')
    			w=-1;
    		ch=getchar();
    	}
        while(isdigit(ch))
            data=10*data+ch-'0',ch=getchar();
        return x=data*w;
    }
    typedef long long ll;
    const int INF=0x7fffffff;
    
    const int MAXN=3e5+7;
    
    int n,m,w[MAXN];
    
    struct node
    {
    	ll ans;
    	ll lmin,rmin,minv,len;
    	
    	inline node operator+(const node&rhs)const
    	{
    		node ret;
    		ret.len=len+rhs.len;
    		if(minv==rhs.minv)
    		{
    			ret.minv=minv;
    			ret.lmin=lmin,ret.rmin=rhs.rmin;
    			ret.ans=ans+rhs.ans+(rmin-1)*(rhs.lmin-1);
    		}
    		else if(minv<rhs.minv)
    		{
    			ret.minv=minv;
    			ret.lmin=lmin,ret.rmin=rmin+rhs.len;
    			ret.ans=ans+rhs.len*(rhs.len+1)/2+(rmin-1)*rhs.len;
    		}
    		else
    		{
    			ret.minv=rhs.minv;
    			ret.lmin=rhs.lmin+len,ret.rmin=rhs.rmin;
    			ret.ans=rhs.ans+len*(len+1)/2+(rhs.lmin-1)*len;
    		}
    		return ret;
    	}
    }seg[MAXN<<2];
    
    ll tag[MAXN<<2];
    
    #define lson (now<<1)
    #define rson (now<<1|1)
    
    void build(int now,int l,int r)
    {
    	tag[now]=0;
    	if(l==r)
    	{
    		seg[now].ans=0;
    		seg[now].lmin=seg[now].rmin=1;
    		seg[now].minv=w[l];
    		seg[now].len=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(lson,l,mid);
    	build(rson,mid+1,r);
    	seg[now]=seg[lson]+seg[rson];
    }
    
    inline void pushdown(int now)
    {
    	if(tag[now])
    	{
    		seg[lson].minv+=tag[now],
    		tag[lson]+=tag[now];
    		seg[rson].minv+=tag[now],
    		tag[rson]+=tag[now];
    		tag[now]=0;
    	}
    }
    
    int ql,qr,v;
    
    void add(int now,int l,int r)
    {
    	if(ql<=l&&r<=qr)
    	{
    		seg[now].minv+=v,
    		tag[now]+=v;
    		return;
    	}
    	pushdown(now);
    	int mid=(l+r)>>1;
    	if(ql<=mid)
    		add(lson,l,mid);
    	if(qr>=mid+1)
    		add(rson,mid+1,r);
    	seg[now]=seg[lson]+seg[rson];
    }
    
    node query(int now,int l,int r)
    {
    	if(ql<=l&&r<=qr)
    	{
    		return seg[now];
    	}
    	pushdown(now);
    	int mid=(l+r)>>1;
    	if(qr<=mid)
    		return query(lson,l,mid);
    	if(ql>=mid+1)
    		return query(rson,mid+1,r);
    	return query(lson,l,mid)+query(rson,mid+1,r);
    }
    
    int main()
    {
      freopen("hotel.in","r",stdin);
      freopen("hotel.out","w",stdout);
    	read(n);read(m);
    	for(int i=1;i<=n;++i)
    		read(w[i]);
    	build(1,1,n);
    	while(m--)
    	{
    		int opt;
    		read(opt);
    		if(opt==1)
    		{
    			read(ql);read(qr);read(v);
    			v=-v;
    			add(1,1,n);
    		}
    		else
    		{
    			read(ql);read(qr);
    			node ans=query(1,1,n);
    			if(ans.minv)
    				printf("%lld
    ",ans.len*(ans.len+1)/2);
    			else
    				printf("%lld
    ",ans.ans);
    		}
    	}
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    
  • 相关阅读:
    Python学习笔模式匹配与正则表达式之管理复杂的正则表达式
    Python学习笔模式匹配与正则表达式之组合使用re.IGNORECASE、re.DOTALL和re.VERBOSE
    Python学习笔模式匹配与正则表达式之电话号码和Email地址提取程序
    Python学习笔记模式匹配与正则表达式之findall()方法
    Python学习笔记模式匹配与正则表达式之字符分类
    瀑布流
    CSS就加了一句话就搞定了!
    CSS笔记
    JS
    三层架构笔记
  • 原文地址:https://www.cnblogs.com/autoint/p/9677788.html
Copyright © 2011-2022 走看看