Hdu 6315 Naive Operations 线段树区间维护

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

Naive Operations

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Others)
Total Submission(s): 1855    Accepted Submission(s): 803

Problem Description

In a galaxy far, far away, there are two integer sequence a and b of length n.
b is a static permutation of 1 to n. Initially a is filled with zeroes.
There are two kind of operations:
1. add l r: add one for al,al+1...ar
2. query l r: query ∑ri=l⌊ai/bi⌋

Input

There are multiple test cases, please read till the end of input file.
For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
In the second line, n integers separated by spaces, representing permutation b.
In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
1≤n,q≤100000, 1≤l≤r≤n, there're no more than 5 test cases.

Output

Output the answer for each 'query', each one line.

Sample Input

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

Sample Output

1 1 2 4 4 6

Source

2018 Multi-University Training Contest 2

题意:给你n个数字,然后q次询问,可能是add或者query。刚开始n个数字都是B数组,然后add操作shi是将A数组(刚开始全部都是0)L----R区间都+1。query操作是将L----R 区间的A[i]/B[i]求和输出。

思路:看到区间修改区间求解问题应该是线段树一类的,但是怎么去求A[i]/B[i]。维护区间最小值,当最小值为0的时候,区间贡献值增加1,暴力下推lazy标记。但是不知道为啥没T。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
const int Maxn=1e6+5;
LL a[maxn];
LL valu[Maxn];//区间最小值 
LL sum[Maxn]; //区间贡献 
LL lazy[Maxn];
void pushup(int id)//从下往上更新 
{
	sum[id] = sum[id<<1] + sum[id<<1|1];
	valu[id] = min(valu[id<<1] , valu[id<<1|1]);
}
void build(int l,int r,int id)//建树 
{
	sum[id]=0;
	lazy[id]=0;
	if(l==r)
	{
		valu[id] = a[l];
		return ;
	}
	int mid = (l+r) >> 1;
	build(l,mid,id<<1);
	build(mid+1,r,id<<1|1);
	pushup(id);
}
void pushdown(int id)//下推 
{
	if(lazy[id])
	{
		lazy[id<<1] = lazy[id<<1] + lazy[id];
		lazy[id<<1|1] = lazy[id<<1|1] + lazy[id];
		valu[id<<1] = valu[id<<1] - lazy[id];
		valu[id<<1|1] = valu[id<<1|1] - lazy[id];
		lazy[id]=0;
	}
}
void Change(int l,int r,int id)
{
	if(l==r)
	{
		lazy[id]=0;
		valu[id]=a[l];//增加贡献 取模 
		sum[id]++;
		return ;
	}
	pushdown(id);
	int mid = (l+r) >> 1;
	if(valu[id<<1] == 0 )
		Change(l,mid,id<<1);
	if(valu[id<<1|1] == 0)
		Change(mid+1,r,id<<1|1);
	pushup(id);
}
void update(int L,int R,int l,int r,int id)//更新 
{
	if(L<=l && R>=r)
	{
		lazy[id]++;
		valu[id]--;
		if(valu[id]==0)//对区间贡献+1 
			Change(l,r,id);
		return ;
	}
	pushdown(id);
	int mid=(l+r) >> 1;
	if(L<=mid)
		update(L,R,l,mid,id<<1);
	if(R>mid)
		update(L,R,mid+1,r,id<<1|1);
	pushup(id);	
}
LL query(int L,int R,int l,int r,int id)//查询 
{
	if(L<=l && R>=r)
		return sum[id];
	pushdown(id);//将存的lazy下推 
	LL ans=0;
	int mid= (l+r) >>1;
	if(L<=mid)
		ans = ans +query(L,R,l,mid,id<<1);
	if(R>mid)
		ans= ans + query (L,R ,mid+1 ,r ,id<<1|1);
	return ans;
}
int main()
{
	int n,q,x,y;
	char s[10];
	while(scanf("%d%d",&n,&q)!=EOF)
	{ 
		for(int i=1;i<=n;i++)
			scanf("%lld",&a[i]);
		build(1,n,1);
		while(q--)
		{
			scanf("%s%d%d",s,&x,&y);
			if(s[0]=='a')
				update(x,y,1,n,1);
			else
				printf("%lld\n",query(x,y,1,n,1));
		}
	}
	return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值