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();}
    
  • 相关阅读:
    Poj 2017 Speed Limit(水题)
    Poj 1316 Self Numbers(水题)
    Poj 1017 Packets(贪心策略)
    Poj 1017 Packets(贪心策略)
    Poj 2662,2909 Goldbach's Conjecture (素数判定)
    Poj 2662,2909 Goldbach's Conjecture (素数判定)
    poj 2388 Who's in the Middle(快速排序求中位数)
    poj 2388 Who's in the Middle(快速排序求中位数)
    poj 2000 Gold Coins(水题)
    poj 2000 Gold Coins(水题)
  • 原文地址:https://www.cnblogs.com/yspm/p/12674022.html
Copyright © 2011-2022 走看看