HDU 4267 线段树 离散点区间更新, 自叶子节点至根单点查询

题意:

n个数字

下面n个数字表示数列

2个操作

1 [u, v]  k  add

[u,v ]区间 (u点要计算)每隔k个位置,该数字+add

 

2 pos

询问 pos下标的值(下标从1开始)

思路:

因为k很小, 可以直接存 k[11]

注意查询时, 先找到 pos 所在的 叶子节点

再向上 添加 对应k位置的值

 

 

 

 

#include<iostream>

#include<stdio.h>

#include<algorithm>

#include<string>

#include<queue>

#include<string.h>

#include<map>

#include<set>

#include<stack>

#include<vector>

#include<math.h>

#define inf 10000000

#define L(x) (x<<1)

#define R(x) (x<<1|1)

#define Mid(x,y) ((x+y)>>1)

#define ll __int64

using namespace std;

inline ll Min(ll a,ll b){return a>b?b:a;}

inline ll Max(ll a,ll b){return a<b?b:a;}



#define N 51000

struct node{

	ll l, r;

	ll k[11];

}tree[N*16];

ll a[N];



void build(ll l, ll r, ll id){

	memset(tree[id].k, 0, sizeof(tree[id].k));

	tree[id].l = l, tree[id].r = r;



	if(l == r)  return ;



	ll mid = Mid(l, r);

	build(l, mid, L(id));

	build(mid+1, r, R(id));

}



void updata(ll l, ll r, ll pos, ll add, ll id){

	if(l > r)return ;

	if(l == tree[id].l && tree[id].r == r)

	{

		tree[id].k[pos] += add;

		return;

	}

	ll mid = Mid(tree[id].l, tree[id].r);

	if(r<=mid)

		updata(l, r, pos, add, L(id));

	else if(mid<l)

		updata(l, r, pos, add, R(id));

	else

	{

		updata(l, mid, pos, add, L(id));

		updata(l + ((mid-l)/pos+1)*pos,r,pos, add, R(id));

	}

}



ll find(ll pos){

	ll id = 1;

	while(1){

		if(tree[id].l == tree[id].r) return id;



		ll mid = Mid(tree[id].l, tree[id].r);

		if(pos <= mid)	id = L(id);

		else			id = R(id);

	}

}



ll query(ll pos, ll id, ll num){

	for(ll i =1;i<11 ;i++)

		if((pos-tree[id].l) % i==0)

			num += tree[id].k[i];



	if(id == 1) return num;

	return query(pos, id/2, num);

}



int main(){

	ll i, j, n, que;

	ll u, v, mod, add;

	while(~scanf("%I64d",&n)){



		for(i=1;i<=n;i++)scanf("%I64d",&a[i]);

		build(1, n, 1);

		scanf("%I64d",&que);

		while(que--){

			scanf("%I64d",&i);

			if(i==2)

			{

				scanf("%I64d",&j);

				printf("%I64d\n",query(j ,find(j), a[j]));

			}

			else

			{

				scanf("%I64d %I64d %I64d %I64d",&u,&v,&mod,&add);

				updata(u, v, mod, add, 1);

			}

		}

	}

	return 0;

}

/*

10

0 0 0 0 0 0 0 0 0 0

99

1 1 10 2 5

2 1

2 2

2 3

2 4

2 5

2 9

2 10

1 3 6 3 10

2 3

2 4

2 5

2 6







ans:

5

0

5

0

5

5

0

15

0

5

10









*/


 

 

你可能感兴趣的:(HDU)