HDU4267 A Simple Problem with Integers

来源:互联网 发布:算法第四版pdf 86mb 编辑:程序博客网 时间:2024/06/05 20:14

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

题意:题目中有两种操作

1.每隔k点更新;

2.查询最底层的叶子节点的值;

思路:因为k不是固定的,但是k的范围又很小,只有1-10,所以我们不妨在每个区域都开一个数组来标记不同的k,代表从最左端的那个点开始,在此区域内,每隔k个点都是有效点。要注意的是,每个区域的起始位置的那个点一定要是有效点。

代码如下:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define L(x) (x<<1)#define R(x) (x<<1|1)#define Mid(x,y) (x+y)>>1const int maxn=50010; int n;int arr[maxn];struct node{int left, right, val[11];}p[4*maxn];void Build(int l, int r, int rt){memset(p[rt].val, 0, sizeof(p[rt].val));p[rt].left=l;p[rt].right=r;if(r==l) return;int mid=Mid(l,r);Build(l, mid, L(rt));Build(mid+1, r, R(rt));}void Update(int l, int r, int k, int c,int rt){if(l>r) return;if(l==p[rt].left && r==p[rt].right){p[rt].val[k]+=c;return;}int mid=Mid(p[rt].left, p[rt].right);if(r<=mid) Update(l,r,k,c,L(rt));else if(l>mid) Update(l,r,k,c,R(rt));else{Update(l,mid,k,c,L(rt));Update(k+l+((mid-l)/k)*k,r,k,c,R(rt)); }     }int find(int u){int rt=1;while(1){if(p[rt].left==p[rt].right) return rt;int mid=Mid(p[rt].left, p[rt].right);if(u<=mid) rt=L(rt);else rt=R(rt);}}int Query(int u, int rt, int num){for(int i=1; i<11; i++){if((u-p[rt].left)%i==0){num+= p[rt].val[i];}} if(rt==1) return num;return Query(u, rt/2, num);          }int main(){while(~scanf("%d", &n)){for(int i=1; i<=n; i++){scanf("%d", &arr[i]);}Build(1,n,1);int m=0,tmp=0;int a,b,k,c;scanf("%d", &m);while(m--){scanf("%d", &tmp);if(tmp==1){scanf("%d%d%d%d", &a, &b, &k, &c);Update(a,b,k,c,1);}if(tmp==2){scanf("%d", &a);printf("%d\n", Query(a,find(a),arr[a]));}}}return 0;}

0 0
原创粉丝点击