HDU 6315 Naive Operations---线段树 2018 Multi-University Training Contest 2

哇!不会写!看了题解之后才明白。令我为自己智商感到担忧。不过真的是一道不错的题目。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6315

题意:给你两个序列,一个序列a,一个序列b,序列a最开始全为0,序列b为你输入的值。你有两种操作。

第一种操作:给序列a的【L,R】区间全部+1

第二种操作 :求和ai/bi , i 属于【L,R】。向下取整。

题解:我们考虑一个实际值。1/5.是0.然后分子+1,2/5还是0,再+1,3/5还是0。只有当我们加够分母的时候,我们才能贡献1的结果。那么回到操作一。我们实际就是给 分子 +1。那么我们 换一种思路考虑。就是给分母-1,当分母为0的时候,我们就可以认为当前节点的贡献值+1.然后再把这个节点恢复到原来的值。那么我们就可以考虑我们的线段树去维护什么。首先我们要维护,某一段区间的贡献值,也就是结果。其次就是某一段区间的最小的值。为什么维护这个呢?我们需要给最小值-1,若最小值到0了。那么贡献就会+1。所以在具体更新操作中。我们只需要判断,某一段的节点的最小值是否为0。为0的话我们需要去到叶节点去更新他。把它回复到b【l】的值。

看代码:

#include<bits/stdc++.h>
using namespace std;

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1

const int maxn = 1e5 + 5;
int sum[maxn << 2],b[maxn << 2],minx[maxn << 2],lazy[maxn<<2]; // sum是结果。b保存原先分母的大小。minx是最小值。 
int n,m;

void pushdown(int rt){   
	minx[rt<<1] -= lazy[rt];
	minx[rt<<1|1] -= lazy[rt];
	lazy[rt<<1] += lazy[rt];
	lazy[rt<<1|1] += lazy[rt];
	lazy[rt] = 0; 
}
void pushup(int rt){
	sum[rt] = sum[rt<<1] + sum[rt<<1|1];
	minx[rt] = min(minx[rt<<1],minx[rt<<1|1]); //维护最小值 
}

void build(int l,int r,int rt){
	if(l > r) return;
	sum[rt] = lazy[rt] = 0;
	if(l == r){   //给叶节点赋值。 
		sum[rt] = lazy[rt] = 0;
		minx[rt] = b[l];
		return ;
	}
	//cout << "GG" << endl;
	int mid = (l+r) >> 1;
	build(lson);
	build(rson);
	pushup(rt);
}
void update(int L,int R,int l,int r,int rt){
    if(L<=l && r<=R)  // 若是子区间。 
    {
        minx[rt] -- ;   ///先给这个区间的-1 
        if(minx[rt]) {  // 判断最小值是否为0 
			lazy[rt]++;  //不为0标记这个区间被减过一次 
			return ;
		}
        else {   // 为0判断是否为叶子节点。若为叶子节点就更新贡献值和恢复原先的分母大小。 
            if(l == r)
            {
                sum[rt] ++;
                minx[rt] = b[l];
                return ;
            } 
        }
    }
    pushdown(rt); //标记下传 
    int mid = (l+r)>>1;
  //  printf("%d  %d\n",mid,L);
    if(L <= mid) update(L,R,lson);
    if(R > mid) update(L,R,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return sum[rt];
    pushdown(rt);
    int mid = (l+r)>>1;
    int ret = 0 ;
    if(L <= mid) ret += query(L,R,lson);
    if(R > mid) ret += query(L,R,rson);
    pushup(rt);
    return ret;
}

int main(){
	while(~scanf("%d%d",&n,&m)){
		for(int i = 1; i <= n ; i ++ )	scanf("%d",&b[i]);
		build(1,n,1);
		while(m--){
			char op[10];
			int l,r;
			scanf("%s%d%d",op,&l,&r);
			if(op[0] == 'a')
				{update(l,r,1,n,1); /*print(1,n,1);&*/}
			else 
				printf("%d\n",query(l,r,1,n,1));
		}
	}
	return 0;
}
/*
5 12
1 5 2 4 3
add 1 4
query 1 4
add 2 5
query 2 5
add 3 5
query 1 5
add 2 4
query 1 4
add 2 5
query 2 5
add 2 2
query 1 5
*/

猜你喜欢

转载自blog.csdn.net/PK__PK/article/details/81241163