HDU-4267:A Simple Problem with Integers(多线段树选择更新)
来源:互联网 发布:北京网络 编辑:程序博客网 时间:2024/05/16 23:34
题目链接:点击打开链接
题意解析:
题意很容易理解就不多讲了。
解题思路:
这道题刚开始想了好久,真不知道怎么做。。。后来看网上博客,大致分为树状数组和线段树两种做法。因为树状数组内存小,代码短,就先学习了树状数组的写法。刚开始看了一篇奇怪的博客,坑了好久,博主用了一种很神奇的方法,看了好长时间看不懂,后来看了些其他博客,终于大致明白了树状数组的写法原理。。。然后又去看了线段树,写之前觉得线段树好难写,后来发现线段树其实比树状数组容易理解的多。先讲树状数组的写法,
题目最主要的部分就是在a,b区间内下标为 i 的数,如果(i-a)%k==0,那么就更新 i 所在的位置的数的值。解题的关键就是化简为 i%k==a%k。要深刻的理解这一点,
从而建立树状数组 d[i][k][mod], mod=a%k, 以此更新,然后树状数组储存的就是每个点的变化值,最后查询的时候输出这个点+它的变化值即可。不过个人认为树状数组还是难以理解,还是线段树好懂,以下先贴树状数组的代码,
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>using namespace std;typedef long long LL;typedef unsigned long long ULL;int n,m;int a[50005];int d[50005][11][11];int sum(int a){ int i=a,s=0; while(i>0) { for(int j=1;j<=10;j++) s += d[i][j][a%j]; i -= i&-i; } return s;}void add(int l,int k,int mod,int c){ int i=l; while(i<=n) { d[i][k][mod] += c; i += i&-i; }}int main(){ while(scanf("%d",&n)!=EOF) { memset(d,0,sizeof(d)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); int p,l,r,k,c; for(int i=0;i<m;i++) { scanf("%d",&p); if(p==1) { scanf("%d%d%d%d",&l,&r,&k,&c); add(l,k,l%k,c); add(r+1,k,l%k,-c); } if(p==2) { scanf("%d",&l); printf("%d\n",a[l]+sum(l)); } } }}
线段树:
线段树的做法相比于树状数组就很容易理解了。
对于 k从1到10,对每个k取余,一共有55种情况,例如1取余1种情况,2取余两种,依次类推,最后能得到55种情况。
那么我们可以根据这55种情况维护55棵线段树,每次更新的时候,选择对应情况的线段树进行更新,听起来55棵线段树真tm吓人,其实还好。就是每个节点里面存了个大小55的数组,大家千万不要被吓到,我刚开始就是被吓到了,所以没写线段树,去搞了什么树状数组,真有点难懂。55棵线段树更新的时候选择对应的更新,然后查询的时候将所有符合要求的线段树的值加上即可,以下贴线段树的代码,
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define lson rt<<1#define rson rt<<1|1using namespace std;typedef long long LL;typedef unsigned long long ULL;int n,m,ans;int a[50005],cc[11];struct tree //sum55就是传说中的55棵线段树{ int l,r,mid; int sum[55]; int mark;}t[200010];void pushdown(int rt) //自上向下维护 注意传给下面节点后要清0{ if(t[rt].mark==-1) { for(int i=0;i<55;i++) { t[lson].sum[i]+=t[rt].sum[i]; t[rson].sum[i]+=t[rt].sum[i]; t[rt].sum[i]=0; } t[rt].mark=0; t[lson].mark=t[rson].mark=-1; }}void build(int l,int r,int rt) //建树过程中初始化 memset貌似会t 队友说的{ int mid=(l+r)>>1; for(int i=0;i<55;i++) t[rt].sum[i]=0; t[rt].l=l;t[rt].r=r; t[rt].mid=mid; t[rt].mark=0; if(l==r) return ; build(l,mid,lson); build(mid+1,r,rson);}void update(int l,int r,int k,int c,int rt){ if(t[rt].l>=l&&t[rt].r<=r) { int co=cc[k-1]+l%k; //选择合适的线段树进行更新 t[rt].sum[co]=t[rt].sum[co]+c; t[rt].mark=-1; return ; } pushdown(rt); if(l<=t[rt].mid) update(l,r,k,c,lson); if(r>t[rt].mid) update(l,r,k,c,rson);}int query(int q,int rt){ if(t[rt].l==t[rt].r&&q==t[rt].l) { int s=0; for(int i=1;i<=10;i++) //将所有符合要求的线段树值加入 s += t[rt].sum[cc[i-1]+q%i]; return s; } pushdown(rt); if(q<=t[rt].mid) return query(q,lson); else return query(q,rson);}int main(){ cc[0]=0; for(int i=1;i<=10;i++) //帮助我们得到每种情况对应到0到54的值 cc[i]=cc[i-1]+i; while(scanf("%d",&n)!=EOF) { build(1,n,1); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); int p,l,r,k,c; for(int i=0;i<m;i++) { scanf("%d",&p); if(p==1) { scanf("%d%d%d%d",&l,&r,&k,&c); update(l,r,k,c,1); } if(p==2) { scanf("%d",&l); ans=a[l]+query(l,1); printf("%d\n",ans); } } }}
阅读全文
0 0
- HDU-4267:A Simple Problem with Integers(多线段树选择更新)
- hdu 4267 A Simple Problem with Integers(线段树)
- HDU 4267 A Simple Problem with Integers(线段树)
- HDU 4267 A Simple Problem with Integers (线段树)
- HDU 4267 A Simple Problem with Integers(线段树)
- HDU 4267 A Simple Problem with Integers (55棵线段树更新维护)
- hdu 4267 A Simple Problem with Integers(线段树区间更新)
- A Simple Problem with Integers (线段树区间更新)
- HDU 4267 A Simple Problem with Integers (线段树)
- 【hdu】A Simple Problem with Integers (线段树)
- A Simple Problem with Integers +poj+线段树区间更新
- poj3468 A Simple Problem with Integers 线段树区间更新
- poj3468 A Simple Problem with Integers 线段树 延时更新
- A Simple Problem with Integers (POJ_3468) 线段树+区间更新
- Poj3468 A Simple Problem with Integers 线段树、区间更新
- A Simple Problem with Integers(线段树 成段更新)
- poj3468 A Simple Problem with Integers 线段树 更新延迟
- 【poj3468-A Simple Problem with Integers】-线段树区间更新
- spark streaming集成kafka接收数据的方式
- QTreeView model/View
- PHP数组的总结
- springboot打成war包
- 前向逐步回归
- HDU-4267:A Simple Problem with Integers(多线段树选择更新)
- c:forEach varStatus属性 current当前这次迭代的(集合中的)项 index当前这次迭代从 0 开始的迭代索引 count当前这次迭代从 1 开始的迭代计数 first用来表明
- new Integer(123)==new Integer(123)为false和new Integer(123)==123为true
- Hadoop集群(高可用)
- android获取PDF文件的缩略图
- Android开发:Binding with unknown activity错误解决方法
- ocp Oracle.1z0-053 711--121
- Java多线程Runnable与Thread的区别
- CTF入门笔记(未完)