【hdu6315】Naive Operations 線段樹

題目大意

給定一個序列b,以及一個初值爲0的序列a。要求支持a的區間+1以及區間詢問a[i]/b[i]的和。

題解

我們考慮對開一個線段樹,每個節點記錄當前a區間最大的值maxa
以及最小的值minb,區間當前情況下的a[i]/b[i]的和cnt,以及lazy標記修改a序列。
每次修改的時候修改maxa。如果當前葉子結點a[i]>=b[i]那麼就將b[i]+=b[i],cnt+1。一直等到a[i]再加到b[i]的時候纔會更新。

代碼

//hdu6315 Naive Operations
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cctype>
#define lson l,mid,st<<1
#define rson mid+1,r,st<<1|1
#define N 100100
using namespace std;
struct Tree{int mxa,mnb,cnt,lazy;}tree[N<<4];
int b[N],n,m;
void pushup(int x)
{
	tree[x].cnt=tree[x<<1].cnt+tree[x<<1|1].cnt;
	tree[x].mnb=min(tree[x<<1].mnb,tree[x<<1|1].mnb);
	tree[x].mxa=max(tree[x<<1].mxa,tree[x<<1|1].mxa);
}
void pushdown(int x)
{
	if (tree[x].lazy==0) return;
	int v=tree[x].lazy;tree[x].lazy=0;
	tree[x<<1].lazy+=v;tree[x<<1|1].lazy+=v;
	tree[x<<1].mxa+=v;tree[x<<1|1].mxa+=v;
}
void build(int l,int r,int st)
{
	if (l==r) {tree[st].mnb=b[l];return;}
	int mid=(l+r)>>1;
	build(lson);build(rson);
	pushup(st);
}
void update(int L,int R,int l,int r,int st)
{
	if (L<=l&&r<=R) 
	{
		tree[st].mxa++;
		if (tree[st].mnb>tree[st].mxa){tree[st].lazy++;return;}
		else
			if (l==r&&tree[st].mnb<=tree[st].mxa) 
			{
				tree[st].cnt++;
				tree[st].mnb+=b[l];
				return;
			}
	}
	pushdown(st);
	int mid=(l+r)>>1;
	if (L<=mid) update(L,R,lson);
	if (R>mid) update(L,R,rson);
	pushup(st);
}
int query(int L,int R,int l,int r,int st)
{
	if (L<=l&&r<=R) return tree[st].cnt;
	int ret=0,mid=(l+r)>>1;
	pushdown(st);
	if (L<=mid) ret+=query(L,R,lson);
	if (R>mid) ret+=query(L,R,rson);
	return ret;
}
int main()
{
	for (;~scanf("%d%d",&n,&m);)
	{
		memset(tree,0,sizeof(tree));
		for (int i=1;i<=n;i++) scanf("%d",&b[i]);
		build(1,n,1);
		for (int i=1;i<=m;i++)
		{
			char ch[6];int L,R;
			scanf("%s%d%d",ch,&L,&R);
			if (ch[0]=='a') update(L,R,1,n,1);
			else printf("%d\n",query(L,R,1,n,1));
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章