Hdu-5828 Rikka with Sequence(线段树)

18 篇文章 0 订阅
Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has an array A with n numbers. Then he makes m operations on it.

There are three type of operations:

1 l r x : For each i in [l,r], change A[i] to A[i]+x
2 l r : For each i in [l,r], change A[i] to A[i]
3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]

It is too difficult for Rikka. Can you help her?
 

Input
The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.

For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.

It is guaranteed that 1<=A[i],x<=100000.
 

Output
For each operation of type 3, print a lines contains one number -- the answer of the query.
 

Sample Input
  
  
1 5 5 1 2 3 4 5 1 3 5 2 2 1 4 3 2 4 2 3 5 3 1 5
 

Sample Output
  
  
5 6


分析:开方最多log(MAXN)次,最终区间会变成一段段连续的数字,然后就可以区间开方了。


#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define MAXN 400005
using namespace std;
struct Segtree
{
	int l,r;
	long long val,tot,down;
	bool yy;
}tree[MAXN];
void push_down(int i)
{
	if(!tree[i].down) return;
	tree[2*i].down += tree[i].down;
	tree[2*i+1].down += tree[i].down;
	tree[2*i].tot += (tree[2*i].r-tree[2*i].l+1ll)*tree[i].down;
	tree[2*i+1].tot += (tree[2*i+1].r-tree[2*i+1].l+1ll)*tree[i].down;
	if(tree[2*i].yy) tree[2*i].val += tree[i].down;
	if(tree[2*i+1].yy) tree[2*i+1].val += tree[i].down;
	tree[i].down = 0;
}
void build(int i,int l,int r)
{
	tree[i].l = l;
	tree[i].r = r;
	tree[i].down = 0;
	if(l == r)
	{
		scanf("%I64d",&tree[i].val);
		tree[i].tot = tree[i].val;
		tree[i].yy = true;
		return;
	}
	int mid = (l+r) >> 1;
	build(2*i,l,mid);
	build(2*i+1,mid+1,r);
	if(tree[2*i].yy && tree[2*i+1].yy && tree[2*i].val == tree[2*i+1].val)
	{
		tree[i].yy = true;
		tree[i].val = tree[2*i].val;
	}
	else tree[i].yy = false;
	tree[i].tot = tree[2*i].tot + tree[2*i+1].tot;
}
int T,n,m;
void add(int i,int x,int y,int val)
{
	int l = tree[i].l,r = tree[i].r;
	if(l == x && r == y)
	{
		tree[i].tot += (y-x+1ll)*val;
		if(tree[i].yy) tree[i].val += val;
		tree[i].down += val;
		return;
	}
	push_down(i);
	int mid = (l+r)/2; 
	if(y <= mid) add(2*i,x,y,val);
	else 
	 if(x <= mid) 
	 {
	 	add(2*i,x,mid,val);
	 	add(2*i+1,mid+1,y,val);
	 }
	 else add(2*i+1,x,y,val);
	if(tree[2*i].yy && tree[2*i+1].yy && tree[2*i].val == tree[2*i+1].val)
	{
		tree[i].yy = true;
		tree[i].val = tree[2*i].val;
	}
	else tree[i].yy = false;
	tree[i].tot = tree[2*i].tot + tree[2*i+1].tot;
}
void sqrtt(int i,int x,int y)
{
	int l = tree[i].l,r = tree[i].r;
	if(l == x && r == y && tree[i].yy)
	{
		tree[i].down += int(sqrt(tree[i].val))-tree[i].val;
		tree[i].val = int(sqrt(tree[i].val));
		tree[i].tot = tree[i].val*(y-x+1ll);
		return;
	}
	push_down(i);
	int mid = (l+r)/2; 
	if(y <= mid) sqrtt(2*i,x,y);
	else 
	 if(x <= mid) 
	 {
	 	sqrtt(2*i,x,mid);
	 	sqrtt(2*i+1,mid+1,y);
	 }
	 else sqrtt(2*i+1,x,y);
	if(tree[2*i].yy && tree[2*i+1].yy && tree[2*i].val == tree[2*i+1].val)
	{
		tree[i].yy = true;
		tree[i].val = tree[2*i].val;
	}
	else tree[i].yy = false;
	tree[i].tot = tree[2*i].tot + tree[2*i+1].tot;
}
long long sumup(int i,int x,int y)
{
	int l = tree[i].l,r = tree[i].r;
	if(l == x && r == y) return tree[i].tot;
	push_down(i);
	int mid = (l+r)/2; 
	if(y <= mid) return sumup(2*i,x,y);
	else 
	 if(x <= mid) return sumup(2*i,x,mid) + sumup(2*i+1,mid+1,y);
	 else return sumup(2*i+1,x,y);
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		build(1,1,n);
		for(int i = 1;i <= m;i++)
		{
			int c;
			scanf("%d",&c);
			if(c == 1)
			{
				int x,y,val;
				scanf("%d%d%d",&x,&y,&val);
				add(1,x,y,val);
			}
			else 
			if(c == 2)
			{
				int x,y;
				scanf("%d%d",&x,&y);
				sqrtt(1,x,y);
			}
			else 
			{
				int x,y;
				scanf("%d%d",&x,&y);
				printf("%I64d\n",sumup(1,x,y));
			}
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值