zoukankan      html  css  js  c++  java
  • 「技巧拾珠」线段树维护区间最值

    线段树区间(min space & & space max) 总结

    有一种题目,让我们求区间取 (min) 和取 (max)

    然后又求和或者其它的操作

    笔者没有见过区间取 (min) 和取 (max) 和其它复杂操作的混合题

    例题:(BZOJ4636) 蒟蒻的数列

    区间取(max+)求和(默认离散化不是一个复杂知识点)

    维护 (3) 个新的 (tag)

    1.区间最小(或者大)值

    2.区间次小(或者大)值

    3.区间最值的个数

    这三个 (tag) 的合并方式不是很复杂,直接上代码理解一下:

    	inline void push_up(int p)
    	{
    		sum(p)=sum(p<<1)+sum(p<<1|1);
    		num(p)=0; maxx(p)=max(maxx(p<<1|1),maxx(p<<1));
    		se(p)=max(se(p<<1),se(p<<1|1));
    		if(maxx(p<<1)!=maxx(p<<1|1)) se(p)=max(se(p),min(maxx(p),maxx(p<<1|1)));
    		if(maxx(p)==maxx(p<<1)) num(p)+=num(p<<1);
    		if(maxx(p)==maxx(p<<1|1)) num(p)+=num(p<<1|1); 
    		return ;
    	}
    

    然后我们这种题目在修改的时候分几种情况讨论:

    1.修改的新 (val) 比最值还最值(省略大小)

    修改并没用,直接返回

    2.比次最值最值,没有最值最值

    (意会吧)

    我们更新一下节点的 (sum)(sum)的更新方式也不难理解,毕竟我们维护了 (num)

    	inline void clear(int p,int val)
    	{
    		if(maxx(p)<=val) return ;
    		sum(p)+=1ll*(val-maxx(p))*num(p);
    		maxx(p)=val;
    	}
    

    (push\_down) 的时候就两个子树和父节点的最值 (clear)(OK)

    然后就是基础操作了(什么?不会? 转去 (Luogu) 模板区吧)

    直接放代码,真的真的好简单,看一遍就能背过(其实就是理解一下,根本不用背)

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=1e5+10;
    	struct node{
    		int l,r,sum,minn,se,num;
    		#define l(p) t[p].l
    		#define r(p) t[p].r
    		#define sum(p) t[p].sum
    		#define minn(p) t[p].minn
    		#define se(p) t[p].se
    		#define num(p) t[p].num
    	}t[N<<2];
    	inline void push_up(int p)
    	{
    		sum(p)=sum(p<<1)+sum(p<<1|1);
    		minn(p)=min(minn(p<<1),minn(p<<1|1));
    		se(p)=min(se(p<<1|1),se(p<<1)); num(p)=0;
    		if(minn(p<<1)!=minn(p<<1|1)) se(p)=min(se(p),max(minn(p<<1),minn(p<<1|1)));
    		if(minn(p)==minn(p<<1|1)) num(p)+=num(p<<1|1);
    		if(minn(p)==minn(p<<1)) num(p)+=num(p<<1);
    		return ;
    	}
    	inline void build(int p,int l,int r)
    	{
    		l(p)=l; r(p)=r; 
    		if(l==r) return num(p)=1,minn(p)=0,sum(p)=0,se(p)=1e15+10,void();
    		int mid=(l+r)>>1;
    		build(p<<1,l,mid); build(p<<1|1,mid+1,r);
    		return push_up(p);
    	}
    	inline void clear(int p,int val)
    	{
    		if(val<=minn(p)) return ;
    		sum(p)+=(val-minn(p))*num(p);
    		minn(p)=val;
    		return ;
    	}
    	inline void spread(int p)
    	{
    		clear(p<<1,minn(p)); clear(p<<1|1,minn(p));
    		return ;
    	}
    	inline void change(int p,int l,int r,int d)
    	{
    		if(l<=l(p)&&r(p)<=r&&d<se(p)) return clear(p,d);
    		spread(p); int mid=(l(p)+r(p))>>1;
    		if(l<=mid) change(p<<1,l,r,d);
    		if(r>mid) change(p<<1|1,l,r,d); 
    		return push_up(p);
    	}
    	inline int ask(int p,int x,int d)
    	{
    		if(l(p)==x&&r(p)==x) return sum(p);
    		spread(p);
    		int mid=(l(p)+r(p))>>1;
    		if(x<=mid) return ask(p<<1,x,d);
    		else return ask(p<<1|1,x,d);
    	}
    	int pos[N],m,l[N],r[N],d[N]; 
    	signed main()
    	{
    		int n=read();
    		for(int i=1;i<=n;++i) 
    		{
    			l[i]=read(); r[i]=read(); d[i]=read();
    			pos[++m]=l[i]; pos[++m]=r[i];
    		}
    		sort(pos+1,pos+m+1); m=unique(pos+1,pos+m+1)-pos-1;
    		for(int i=1;i<=n;++i)
    		{
    			l[i]=lower_bound(pos+1,pos+m+1,l[i])-pos;
    			r[i]=lower_bound(pos+1,pos+m+1,r[i])-pos;
    		}build(1,1,m);
    		for(int i=1;i<=n;++i){
    			change(1,l[i],r[i]-1,d[i]);
    		}
    		int ans=0;
    		for(int i=1;i<=m;++i)
    		{
    			int res=ask(1,i,i);
    			ans+=res*(pos[i+1]-pos[i]);
    		} printf("%lld
    ",ans); 
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    让 .Net 程序 脱离 .net framework框架 运行的方法 转
    MySpaces性能提高的过程转
    AskNet 内容查询系统 筹备中
    关于自定义表单的一些想法
    Url重写
    show一下我的办公桌
    IronRuby 初览
    微软将终止对SQL2000的支持
    WCF 消息交换 转
    感受刘德华的努力
  • 原文地址:https://www.cnblogs.com/yspm/p/12674022.html
Copyright © 2011-2022 走看看