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 4267 线段树 离散点区间更新, 自叶子节点至根单点查询)