zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    42. Trapping Rain Water
    223. Rectangle Area
    645. Set Mismatch
    541. Reverse String II
    675. Cut Off Trees for Golf Event
    安装 VsCode 插件安装以及配置
    向上取整 向下取整 四舍五入 产生100以内随机数
    JS 判断是否为数字 数字型特殊值
    移动端初始配置,兼容不同浏览器的渲染内核
    Flex移动布局中单行和双行布局的区别以及使用
  • 原文地址:https://www.cnblogs.com/void-f/p/9372092.html
Copyright © 2011-2022 走看看