[HDU6315]Naive Operations(线段树+树状数组)

Posted void-f

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDU6315]Naive Operations(线段树+树状数组)相关的知识,希望对你有一定的参考价值。

构造一个序列B[i]=-b[i],建一颗线段树,维护区间max,

每次区间加后再询问该区间最大值,如果为0就在树状数组中对应的值+1(该操作可能进行多次)

答案在树状数组中找

其实只用一颗线段树也是可以的

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#define mst(a) memset(a,0,sizeof(a))
#define N 100010
using namespace std;

int n,m,b[N];

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*10+ch-‘0‘;ch=getchar();}
	return x*f;
}

namespace BT{
	int T[N];
	#define lowbit(x) ((x)&(-x))
	void add(int x,int v){for(;x<=n;x+=lowbit(x))T[x]+=v;}
	int Q(int x){int r=0;for(;x;x-=lowbit(x))r+=T[x];return r;}
	void ntt(){mst(T);}
}

namespace Seg{
	#define MID int mid=(l+r)>>1,ls=id<<1,rs=id<<1|1
	int tag[N*4];
	struct info{
		int x,id;
		info(){x=id=0;}
		info(int a,int b):x(a),id(b){}
		friend info operator+(info a,info b){
			return a.x>b.x?a:b;
		}
	}T[N*4];
	void build(int l,int r,int id){
		if(l==r){T[id]=info(-b[l],l);return;}
		MID;
		build(l,mid,ls),build(mid+1,r,rs);
		T[id]=T[ls]+T[rs];
	}
	void pushdown(int l,int r,int id){
		int &tmp=tag[id];
		if(!tmp)return;
		MID;
		tag[ls]+=tmp,tag[rs]+=tmp;
		T[ls].x+=tmp,T[rs].x+=tmp;
		tmp=0;
	}
	void upd(int l,int r,int id,int L,int R,int v){
		if(L<=l&&r<=R){tag[id]+=v;T[id].x+=v;return;}
		pushdown(l,r,id);
		MID;
		if(L<=mid)upd(l,mid,ls,L,R,v);
		if(R>=mid+1)upd(mid+1,r,rs,L,R,v);
		T[id]=T[ls]+T[rs];
	}
	info Q(int l,int r,int id,int L,int R){
		if(L<=l&&r<=R){return T[id];}
		pushdown(l,r,id);
		MID;
		info res(-1e9,0);
		if(L<=mid)res=res+Q(l,mid,ls,L,R);
		if(R>=mid+1)res=res+Q(mid+1,r,rs,L,R);
		return res;
	}
	void fft(){mst(tag),mst(T);}
}
void fwt(){Seg::fft(),BT::ntt();}
int main(){
	for(;~scanf("%d%d",&n,&m);){
		fwt();
		for(int i=1;i<=n;++i)b[i]=read();
		Seg::build(1,n,1);
		for(int i=1;i<=m;++i){
			char s[10];scanf("%s",s);
			int l=read(),r=read();
			if(s[0]==‘a‘){
				Seg::upd(1,n,1,l,r,1);
				for(;;){
					Seg::info tmp=Seg::Q(1,n,1,l,r);
					if(tmp.x==0){
						Seg::upd(1,n,1,tmp.id,tmp.id,-b[tmp.id]);
						BT::add(tmp.id,1);
					}else break;
				}
				
			}else printf("%d
",BT::Q(r)-BT::Q(l-1));
		}
	}
	return 0;
}

 

以上是关于[HDU6315]Naive Operations(线段树+树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

HDU6315 Naive Operations(多校第二场1007)(线段树)

[HDU6315]Naive Operations(线段树+树状数组)

HDU-DuoXiao第二场hdu 6315 Naive Operations 线段树

HDU6315 Naive Operations(线段树 复杂度分析)

Naive Operations HDU6315 (杭电多校2G)

HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)