HDU4267(2012年长春站)
2016-02-27 09:05
169 查看
这道题真的是好题,让我对线段树有了全新的认识,至少让我真正感受到了线段树的神奇。
题意是就是线段树区间更新,单点询问的问题,不过这个题好就好在它的区间更新的点并不连续!
adding c to each of Ai which satisfies a <= i <= b and (i - a) % k == 0.
关键在于更新的点所满足的条件 1.在区间[a,b]中。 2.关于k的余数与(a%k)相等。
其中第二个条件保证了更新的点不连续(但如果传统的先判断再更新,则线段树失去了优势,因为始终会超时)。
本题突破口在于K的大小(1 <= k <= 10),结合第二个条件,我们可以想到在线段树的 Lazy标记上做文章。
当k==1 余数有 0
当k==2 余数有 0,1
当k==3 余数有 0,1,2
。。。。。
可以看到,只有55种情况,那么我们只需要将线段树的 Lazy标记 扩充为大小55的数组,
然后根据相应的余数情况进行更新与查询即可。
不过感觉自己的代码风格还不够成熟,继续努力!
题意是就是线段树区间更新,单点询问的问题,不过这个题好就好在它的区间更新的点并不连续!
adding c to each of Ai which satisfies a <= i <= b and (i - a) % k == 0.
关键在于更新的点所满足的条件 1.在区间[a,b]中。 2.关于k的余数与(a%k)相等。
其中第二个条件保证了更新的点不连续(但如果传统的先判断再更新,则线段树失去了优势,因为始终会超时)。
本题突破口在于K的大小(1 <= k <= 10),结合第二个条件,我们可以想到在线段树的 Lazy标记上做文章。
当k==1 余数有 0
当k==2 余数有 0,1
当k==3 余数有 0,1,2
。。。。。
可以看到,只有55种情况,那么我们只需要将线段树的 Lazy标记 扩充为大小55的数组,
然后根据相应的余数情况进行更新与查询即可。
#include<iostream> #include<sstream> #include<stack> #include<cstdio> #include<cstdlib> #include<cstring> #include<climits> #include<cctype> #include<queue> #include<algorithm> #include<cmath> #include<map> #include<set> #define lson root<<1,l,mid #define rson root<<1|1,mid+1,r #define inf 0x3f3f3f3f #define N 50010 #define maxn 10001000 #define mod 1000000007 using namespace std; int a ; int b[11][11]; //用于将55种余数情况一 一 对 应 struct NODE{ int l,r; int v; int b[55]; int mid(){ return (l+r)>>1; } }node[N<<2]; void build(int root,int l,int r) { node[root].l=l; node[root].r=r; node[root].v=0; memset(node[root].b,0,sizeof(node[root].b)); if(l==r) return; int mid=node[root].mid(); build(lson); build(rson); } void pushdown(int root) //关于pushdown函数,个人觉得只需要询问时调用就行了,而且也过了,应该没问题,有的话请指出,谢谢 { for(int i=1; i<=10; ++i) { for(int j=0; j<i; ++j) { node[root<<1].b[b[i][j]]+=node[root].b[b[i][j]]; node[root<<1|1].b[b[i][j]]+=node[root].b[b[i][j]]; } } memset(node[root].b,0,sizeof(node[root].b)); } void update(int x,int y,int root,int v,int k,int rd) { if(node[root].l==x&&node[root].r==y) { node[root].b[b[k][rd]]+=v; node[root].v+=v; return; } int mid=node[root].mid(); if(y<=mid) update(x,y,root<<1,v,k,rd); else if(x>mid) update(x,y,root<<1|1,v,k,rd); else { update(x,mid,root<<1,v,k,rd); update(mid+1,y,root<<1|1,v,k,rd); } } int query(int root,int x) { if(node[root].l==x&&node[root].r==x) { int ans=0; for(int i=1; i<=10; ++i) ans+=node[root].b[b[i][x%i]]; return ans; } pushdown(root); int mid=node[root].mid(); if(x<=mid) return query(root<<1,x); else return query(root<<1|1,x); } int main() { // freopen("lxx.txt","r",stdin); int group,figure,i,j,x,y,k,v,num; int cnt=0; for(i=1; i<=11; ++i) for(j=0; j<i; ++j) b[i][j]=cnt++; while(~scanf("%d",&group)) { build(1,1,group); memset(a,0,sizeof(a)); for(i=1; i<=group; ++i) scanf("%d",&a[i]); scanf("%d",&group); while(group--) { scanf("%d",&num); if(num==1) { scanf("%d%d%d%d",&x,&y,&k,&v); update(x,y,1,v,k,x%k); } else { scanf("%d",&figure); printf("%d\n",query(1,figure)+a[figure]); } } } return 0; }
不过感觉自己的代码风格还不够成熟,继续努力!
相关文章推荐
- web storage和cookie的区别
- 一个双网卡导致的网络故障
- NU1002 The dependency Microsoft.AspNet.Mvc 5.2.3 in project dotnetstarter does not support framework
- 微软How-old(照片识别年龄)数据交互流程分析
- redis replication问题一解
- 网络性能测试
- 关于坐标系与经纬度
- 微信开放平台之公众号第三方平台开发及全网发布验证
- 【设计模式】备忘录模式
- ubuntu server设置时区和更新时间
- 开源代码应用之Eclipse篇
- Objective-C 高性能的循环遍历 forin - NSEnumerator - 枚举 优化
- java 正则
- JS原型、原型链深入理解
- 移动互联网实时视频通讯之视频采集
- C 基础——指针函数与函数指针
- p_thread学习笔记
- Android.mk的一些FAQ
- 【UVa10054】The Necklace【欧拉回路】
- 应用开机启动及相关文档翻译