zoukankan      html  css  js  c++  java
  • UOJ#164:【清华集训2015】V

    浅谈区间最值操作与历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html

    题目传送门:http://uoj.ac/problem/164

    论文题。论文做法如下:

    首先我们定义一种标记((a,b)),表示给这个区间先加上(a)再跟(b)(max),不难发现题目里提到的三种操作分别都可以用这样的标记来代替:

    1、区间加(v)((v,-inf))

    2、区间减(v)((-v,0))

    3、区间覆盖:((-inf,v))

    考虑合并两个标记((a,b),(c,d)),那么就会变成((a+c,max(b+c,d)))

    现在考虑历史标记最大值,对于一个标记,我们可以将它看成是一个分段函数。第一段的函数是(y=b),第二段的函数是(y=x+a)。那么历史最大标记则可以用((max(a,c),max(b,d)))来表示。如下图,红色的部分就是历史标记最大值:

    时间复杂度:(O(nlogn))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const ll inf=1e18;
    const int maxn=5e5+5;
    
    int n,m;
    int a[maxn];
    
    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*10+ch-'0';
    	return x*f;
    }
    
    struct segment_tree {
    	struct tag {
    		ll add,mx;
    
    		void init() {
    			add=0,mx=-inf;
    		}
    
    		tag() {}
    
    		tag(ll _add,ll _mx) {
    			add=_add,mx=_mx;
    		}
    
    		tag operator+(const tag &a)const {
    			return tag(max(-inf,add+a.add),max(mx+a.add,a.mx));
    		}
    
    		tag operator*(const tag &a)const {
    			return tag(max(add,a.add),max(mx,a.mx));
    		}
    	};
    
    	struct tree_node {
    		ll hismx,mx;
    		tag his,now;
    	}tree[maxn<<2];
    
    	void update(int p) {
    		tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx);
    		tree[p].hismx=max(tree[p<<1].hismx,tree[p<<1|1].hismx);
    	}
    
    	void build(int p,int l,int r) {
    		tree[p].his.init(),tree[p].now.init();
    		if(l==r) {tree[p].hismx=tree[p].mx=a[l];return;}
    		int mid=(l+r)>>1;
    		build(p<<1,l,mid),build(p<<1|1,mid+1,r);
    		update(p);
    	}
    
    	void make_tag(int p,tag now,tag his) {
    		tree[p].his=tree[p].his*(tree[p].now+his);
    		tree[p].now=tree[p].now+now;
    		ll res=max(tree[p].mx+his.add,his.mx);
    		tree[p].hismx=max(tree[p].hismx,res);
    		tree[p].mx=max(tree[p].mx+now.add,now.mx);
    	}
    
    	void push_down(int p) {
    		make_tag(p<<1,tree[p].now,tree[p].his);
    		make_tag(p<<1|1,tree[p].now,tree[p].his);
    		tree[p].now.init(),tree[p].his.init();
    	}
    
    	void change(int p,int l,int r,int L,int R,ll v,ll mx) {
    		if(L<=l&&r<=R) {make_tag(p,tag(v,mx),tag(v,mx));return;}
    		int mid=(l+r)>>1;push_down(p);
    		if(L<=mid)change(p<<1,l,mid,L,R,v,mx);
    		if(R>mid)change(p<<1|1,mid+1,r,L,R,v,mx);
    		update(p);
    	}
    
    	ll query(int p,int l,int r,int pos,int opt) {
    		if(l==r) return opt==4?tree[p].mx:tree[p].hismx;
    		int mid=(l+r)>>1;push_down(p);
    		if(pos<=mid)return query(p<<1,l,mid,pos,opt);
    		else return query(p<<1|1,mid+1,r,pos,opt);
    	}
    }T;
    
    int main() {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read();
    	T.build(1,1,n);
    	for(int i=1;i<=m;i++) {
    		int opt=read(),l=0,r=0,v=0,pos=0;
    		if(opt>3)pos=read();
    		else l=read(),r=read(),v=read();
    		if(opt==1)T.change(1,1,n,l,r,v,-inf);
    		if(opt==2)T.change(1,1,n,l,r,-v,0);
    		if(opt==3)T.change(1,1,n,l,r,-inf,v);
    		if(opt>3)printf("%lld
    ",T.query(1,1,n,pos,opt));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Task10 文本预处理
    Task09 批量归一化
    Task06 Basic of CNN
    Task05 梯度消失和梯度爆炸
    Task 04 过拟合,欠拟合及其解决方案
    机器学习 Task 03 多层感知机
    机器学习 task2 softmax与分类模型
    异步与闭包与fetch
    baidu API
    my own JSON
  • 原文地址:https://www.cnblogs.com/AKMer/p/10241514.html
Copyright © 2011-2022 走看看