• 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
    ",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
    
    
    
    
    */


     

  • 相关阅读:
    回调函数中调用类中的非静态成员变量或非静态成员函数
    [NewCoder]复杂链表的复制
    C++对象模型--总结
    chunk writer 中需要对抛错的交易进行回滚,同时又要在其他表中记录是哪一笔交易记录失败
    为什么因式分解n=pq分别得到pq是求解密钥中d的关键
    DB2 创建数据库
    socket 收发报文小程序
    Zbrush Topogun 备忘
    过度科目理解
    借贷记账思考2015.12.28
  • 原文地址:https://www.cnblogs.com/riasky/p/3431154.html
Copyright © 2020-2023  润新知