HDU 4267 A Simple Problem with Integers(2012年长春网络赛A 多颗线段树+单点查询)
以前似乎做过类似的不过当时完全不会。现在看到就有点思路了,开始还有洋洋得意得觉得自己有不小的进步了,结果思路错了。。。改了很久后测试数据过了还果断爆空间。。。
给你一串数字A,然后是两种操作:
"1 l r k c":意思是当 l=<i<=r 对(i-a)%k = =0 的每个 Ai 都增加 c (1=<k<=10)
"2 i" :意思是求出 Ai
一看就是区间更新和单点查询,其实可以用树状数组做,可是觉得线段树好弄一点,结果成功入坑。。。
我们可以发现k特别的小,而对于每一位的k,都有k个不同的余数,所以可以从这儿入手。可以看出对于每一个k,难点在于区间更新的时候并不是一定严格+1的连续区间,但是一定是+k连续区间,所以:
k=1,建一棵从1开始每次+1的树
k=2,建一棵从1开始每次+2的树 建一颗从2开始每次+2的树
k=3,建一棵从1开始每次+3的树 建一颗从2开始每次+3的树 建一棵从3开始每次+3的树
......
建立55棵线段树
但是如果就直接建立55颗线段树,再建55个对应的更新树,则会爆空间。不过我们可以看是单点查询,根本不需要用父节点记录孩子节点的和,建立线段树仅仅是为了区间更新。所以就可以直接模拟更新树,每个节点记录是此区间每个位置需要增加的值,求值的时候下更新到叶子节点就可以了。注意因为输入的l不是一定对应每棵树的l位置(不是每次都+1),所以我们要处理l,还有就是[l,r]之间我们仅仅更新一些点,右端点要处理好。最后查询的时候要查询10棵树
本以为对线段树有些心得了,可是对于有一点变化的东西都不能灵活运用,还需努力了
- #include<set>
- #include<map>
- #include<queue>
- #include<stack>
- #include<cmath>
- #include<vector>
- #include<string>
- #include<cstdio>
- #include<cstring>
- #include<stdlib.h>
- #include<iostream>
- #include<algorithm>
- using namespace std;
- #define eps 1E-8
- /*注意可能会有输出-0.000*/
- #define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
- #define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
- #define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
- #define mul(a,b) (a<<b)
- #define dir(a,b) (a>>b)
- typedef long long ll;
- typedef unsigned long long ull;
- const int Inf=<<;
- const double Pi=acos(-1.0);
- const int Max=<<;
- int segtr[Max][];//建立55棵线段树 因为是单点查询,所以每次查询到孩子节点,父节点就只需要记录孩子增加了多少,所以线段树节点就模拟更新的树就好
- int per[Max],pos[][];//记录初始值 记录节点在树的位置
- void Create(int sta,int enn,int now)
- {
- memset(segtr[now],,sizeof(segtr[now]));
- if(sta==enn)
- {
- scanf("%d",&per[sta]);
- return;
- }
- int mid=dir(sta+enn,);
- int next=mul(now,);
- Create(sta,mid,next);
- Create(mid+,enn,next|);
- return;
- }
- void Downow(int now,int next,int k)//区间更新的关键
- {
- if(segtr[now][k])//相当于区间更新
- {
- segtr[next][k]+=segtr[now][k];
- segtr[next|][k]+=segtr[now][k];
- segtr[now][k]=;
- }
- return;
- }
- void Update(int sta,int enn,int now,int x,int y,int k,int add)
- {
- if(sta>=x&&enn<=y)
- {
- segtr[now][k]+=add;
- return;
- }
- int mid=dir(sta+enn,);
- int next=mul(now,);
- Downow(now,next,k);//只需要下更新
- if(mid>=x)
- Update(sta,mid,next,x,y,k,add);
- if(mid<y)
- Update(mid+,enn,next|,x,y,k,add);
- return;
- }
- int Query(int sta,int enn,int now,int x,int k)
- {
- if(sta==enn)
- {
- return segtr[now][k];
- }
- int mid=dir(sta+enn,);
- int next=mul(now,);
- Downow(now,next,k);//只需要下更新
- if(mid>=x)
- return Query(sta,mid,next,x,k);
- else
- return Query(mid+,enn,next|,x,k);
- }
- int main()
- {
- int n,q,coun=;
- for(int i=;i<;i++)
- for(int j=;j<=i;j++)
- pos[i][j]=coun++;
- while(~scanf("%d",&n))
- {
- Create(,n,);
- scanf("%d",&q);
- int typ,lef,rig,k;
- int add;
- while(q--)
- {
- scanf("%d",&typ);
- if(typ==)
- {
- add=;
- scanf("%d",&lef);
- for(int i=; i<; i++)//查询时需要查询10棵树
- add+=Query(,n,,(lef+i)/(i+),pos[i][(lef-)%(i+)]);//相同大小在每棵树的位置不一样,注意
- add+=per[lef];
- printf("%d\n",add);
- }
- else
- {
- scanf("%d %d %d %d",&lef,&rig,&k,&add);//只是更新一棵树就好
- Update(,n,,(lef+k-)/k,(rig-lef)/k+(lef+k-)/k,pos[k-][(lef-)%k],add);//注意更新的只是输入的左右区间内的一部分
- }
- }
- }
- return ;
- }
HDU 4267 A Simple Problem with Integers(2012年长春网络赛A 多颗线段树+单点查询)的更多相关文章
- HDU 4267 A Simple Problem with Integers
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K ...
- HDU 4267 A Simple Problem with Integers(树状数组区间更新)
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K ...
- 【树状数组区间修改单点查询+分组】HDU 4267 A Simple Problem with Integers
http://acm.hdu.edu.cn/showproblem.php?pid=4267 [思路] 树状数组的区间修改:在区间[a, b]内更新+x就在a的位置+x. 然后在b+1的位置-x 树状 ...
- HDU 4267 A Simple Problem with Integers --树状数组
题意:给一个序列,操作1:给区间[a,b]中(i-a)%k==0的位置 i 的值都加上val 操作2:查询 i 位置的值 解法:树状数组记录更新值. 由 (i-a)%k == 0 得知 i%k == ...
- 2012年长春网络赛(hdu命题)
为迎接9月14号hdu命题的长春网络赛 ACM弱校的弱菜,苦逼的在机房(感谢有你)呻吟几声: 1.对于本次网络赛,本校一共6名正式队员,训练靠的是完全的自主学习意识 2.对于网络赛的群殴模式,想竞争现 ...
- HDOJ 4267 A Simple Problem with Integers (线段树)
题目: Problem Description Let A1, A2, ... , AN be N elements. You need to deal with two kinds of opera ...
- HDU 4747 Mex (2013杭州网络赛1010题,线段树)
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- HDU 3974 Assign the task(DFS序+线段树单点查询,区间修改)
描述There is a company that has N employees(numbered from 1 to N),every employee in the company has a ...
- 【HDOJ】4267 A Simple Problem with Integers
树状数组.Easy. /* 4267 */ #include <iostream> #include <string> #include <map> #includ ...
随机推荐
- Angular 资料大集合
https://angular.cn/ Angular 的中文网 http://www.apjs.net/#dir1 Angular 的中文网 http://www.ngnice.com/ ...
- JFinal中json的使用
之前Java开发一直使用的是经典的ssh,去年接触了jfinal,觉得jfinal的魅力非常之大,让我无法自拔,现在还深深地陷在其中. 简单的介绍一下jfinal,jfinal短小精悍,让java有了 ...
- 转:什么是Node.js?
Node不是万能药!但的确能解决一些关键问题 学习Node不是一件轻松事儿,但你所收到的回报是对得起你的付出的.因为当下Web应用开发中的诸多难题唯有JavaScript才能解决. 目录 专家们的警告 ...
- iOS swift 给MBProgressHUD添加分类
MBProgressHUD在开发中经常会用到,今天把MBProgressHUD的方法拓展了一下,更加方便使用 1.可以实现gif图片的展示,使用时请替换test.gif 2.可以控制是否允许交互,如果 ...
- 50条SQL查询技巧、查询语句示例
学习了 1.查询“001”课程比“002”课程成绩高的所有学生的学号: 2.查询平均成绩大于60分的同学的学号和平均成绩: 3.查询所有同学的学号.姓名.选课数.总成绩: 4.查询姓“李”的老师的个数 ...
- python的list求和与求积
python中,无论是对的list求和还是求积,我都给出了两种方法. 1.对list求和 1.1 s=0 for i in range(10): s+=i 1.2 s=sum(range(10)) 2 ...
- oracle10g卸载问题
oracle10g卸载是一个比较麻烦的事,一般要完全卸载有以下几个步骤: 实现方法:1.开始->设置->控制面板->管理工具->服务停止所有Oracle服务:2.开始-> ...
- vue实践---vue不依赖外部资源实现简单多语
vue使用多语,最常见的就是 vue-i18n, 但是如果开发中的多语很少,比如就不到10个多语,这样就没必要引入vue-i18n了, 引入了反正导致代码体积大了,这时候单纯用vue实现多语就是比较好 ...
- 在Hierarchy面板隐藏物体
PlantObjPreview.hideFlags = HideFlags.HideInHierarchy;
- JUNIT单元测试时统计代码的覆盖率工具eclemma安装
EclEmma是Eclipse里的一个插件,安装简单,覆盖率显示直观.安装EclEmma.打开Eclipse,点击Help → Software Updates → Find and Install, ...