HDU 4027 Can you answer these queries?(线段树单点更新+询问+神坑)
来源:互联网 发布:淘宝小也香水是正品吗 编辑:程序博客网 时间:2024/06/02 04:31
A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapon to eliminate the battleships. Each of the battleships can be marked a value of endurance. For every attack of our secret weapon, it could decrease the endurance of a consecutive part of battleships by make their endurance to the square root of it original value of endurance. During the series of attack of our secret weapon, the commander wants to evaluate the effect of the weapon, so he asks you for help.
You are asked to answer the queries that the sum of the endurance of a consecutive part of the battleship line.
Notice that the square root operation should be rounded down to integer.
You are asked to answer the queries that the sum of the endurance of a consecutive part of the battleship line.
Notice that the square root operation should be rounded down to integer.
For each test case, the first line contains a single integer N, denoting there are N battleships of evil in a line. (1 <= N <= 100000)
The second line contains N integers Ei, indicating the endurance value of each battleship from the beginning of the line to the end. You can assume that the sum of all endurance value is less than 2 63.
The next line contains an integer M, denoting the number of actions and queries. (1 <= M <= 100000)
For the following M lines, each line contains three integers T, X and Y. The T=0 denoting the action of the secret weapon, which will decrease the endurance value of the battleships between the X-th and Y-th battleship, inclusive. The T=1 denoting the query of the commander which ask for the sum of the endurance value of the battleship between X-th and Y-th, inclusive.
101 2 3 4 5 6 7 8 9 1050 1 101 1 101 1 50 5 81 4 8
Case #1:1976
题解:
这题难度不大,坑点特多,不过也学到了很多,让我感到疑问的是,我用同样的代码,把里面父子节点的*号和+号改成了位运算。。结果用的时间居然更!多!了,测试了2组,平均都比加号乘号多了100-200ms,这和学长说的位运算会更快得出了相反的结论(也可能是测试数据过少),学到的是在建树的时候赋值会快上一倍,以前都是用数组保存好再建的,费时间又废内存,还有这题就是我看了几篇博客都是用打tag的方法确定区间是否全部为1的以节省时间。。后来不记得在哪看到的用的方法很巧妙,用询问区间来确定要不要更新,如果被询问的区间x,y值为y-x+1,就不更新,虽然好像更慢一些但是操作起来简单。。记笔记
代码:
#include<algorithm>#include<iostream>#include<cstring>#include<stdio.h>#include<math.h>#include<string>#include<stdio.h>#include<queue>#include<stack>#include<map>#include<deque>using namespace std;struct node{ int l,r; long long sum;//给的范围要求用long long};node t[400005];void Build(int l,int r,int num){ t[num].l=l; t[num].r=r; if(l==r) { scanf("%lld",&t[num].sum);//要直接在里面建树,不能用数组保存后建,会超时 return; } int mid=(l+r)/2; Build(l,mid,num*2); Build(mid+1,r,num*2+1); t[num].sum=t[num*2].sum+t[num*2+1].sum;//更新一波数据}void update(int l,int r,int num)//日常更新{ if(t[num].l==t[num].r) { t[num].sum=sqrt(t[num].sum); return; } int mid=(t[num].l+t[num].r)/2; if(r<=mid) update(l,r,num*2); else if(l>mid) update(l,r,num*2+1); else { update(l,mid,num*2); update(mid+1,r,num*2+1); } t[num].sum=t[num*2].sum+t[num*2+1].sum;//相当于pushup向上更新}long long query(int l,int r,int num)//询问{ if(l==t[num].l&&r==t[num].r)//与平常不同,由于是单点更新,区间左右端点相同就是访问区间的单点 { return t[num].sum; } int mid=(t[num].l+t[num].r)/2; if(r<=mid) return query(l,r,num*2); else if(l>mid) return query(l,r,num*2+1); else return query(l,mid,num*2)+query(mid+1,r,num*2+1);}int main(){ int i,j,n,m,x,y,d,k,ans=1; while(scanf("%d",&n)!=EOF&&n) { Build(1,n,1); scanf("%d",&m); printf("Case #%d:\n",ans); ans++; for(i=0;i<m;i++) { scanf("%d%d%d",&d,&x,&y); if(x>y)//神坑,去掉会错。。故意的 swap(x,y); if(d==0) { if(query(x,y,1)!=y-x+1)//精华,如果区间全是1,就不用更新了,去掉tle update(x,y,1); } else { printf("%lld\n",query(x,y,1)); } } printf("\n"); } return 0;}
然后这是我自己想的第二种做法,比前一种还快200ms-300ms,就是区间打tag的方法,如果是1就tag为0,不是1就tag为1,如果区间tag和为0就不用找或者修改了,这里就不打备注了,都差不多
#include<algorithm>#include<iostream>#include<cstring>#include<stdio.h>#include<math.h>#include<string>#include<stdio.h>#include<queue>#include<stack>#include<map>#include<deque>using namespace std;const int N=1e5+5;struct node{ int l,r; int tag; long long sum;}t[N*4];void Build(int l,int r,int num){ t[num].l=l; t[num].r=r; if(l==r) { scanf("%lld",&t[num].sum); if(t[num].sum!=1) t[num].tag=1; else t[num].tag=0; return; } int mid=(l+r)/2; Build(l,mid,num*2); Build(mid+1,r,num*2+1); t[num].tag=t[num*2].tag+t[num*2+1].tag; t[num].sum=t[num*2].sum+t[num*2+1].sum;}long long query(int l,int r,int num){ if(t[num].tag==0) { return r-l+1; } if(l==t[num].l&&r==t[num].r) { return t[num].sum; } int mid=(t[num].l+t[num].r)/2; if(r<=mid) return query(l,r,num*2); else if(l>mid) return query(l,r,num*2+1); else return query(l,mid,num*2)+query(mid+1,r,num*2+1);}void update(int l,int r,int num){ if(t[num].tag==0) return; if(t[num].l==t[num].r) { t[num].sum=sqrt(t[num].sum); if(t[num].sum==1) t[num].tag=0; return; } int mid=(t[num].l+t[num].r)/2; if(r<=mid) update(l,r,num*2); else if(l>mid) update(l,r,num*2+1); else { update(l,mid,num*2); update(mid+1,r,num*2+1); } t[num].tag=t[num*2].tag+t[num*2+1].tag; t[num].sum=t[num*2].sum+t[num*2+1].sum;}int main(){ int n,i,j,k,x,y,q,ans=1; while(scanf("%d",&n)!=EOF) { Build(1,n,1); scanf("%d",&k); printf("Case #%d:\n",ans); ans++; for(i=0;i<k;i++) { scanf("%d%d%d",&q,&x,&y); if(x>y) swap(x,y); if(q==0) update(x,y,1); else printf("%lld\n",query(x,y,1)); } printf("\n"); } return 0;}
阅读全文
0 0
- HDU 4027 Can you answer these queries?(线段树单点更新+询问+神坑)
- hdu 4027 Can you answer these queries? 线段树 懒惰标记 单点更新妙用
- HDU 4027 Can you answer these queries?(线段树单点更新)
- HDU4027:Can you answer these queries?(线段树单点更新)
- Can you answer these queries?(线段树之单点更新)
- hdu 4027 Can you answer these queries?(线段树)(单点更新 但需要标记记录剪枝)
- 【HDU】4027 Can you answer these queries? (线段树)
- HDU 4027 Can you answer these queries(线段树)
- hdu 4027 Can you answer these queries?(线段树)
- HDU - 4027 Can you answer these queries?(线段树)
- HDU 4027 Can you answer these queries?(线段树)
- HDU 4027 Can you answer these queries?(线段树)
- HDU-4027-Can you answer these queries?(线段树)
- HDU 4027 Can you answer these queries? (线段树)
- hdu 4027 Can you answer these queries? (线段树)
- hdu 4027 Can you answer these queries?(线段树——区间更新)(思路)
- HDU 4027 Can you answer these queries(线段树 成段更新)
- HDU 4027 Can you answer these queries? (线段树 区间更新)
- log4j框架logger的继承关系以及使用场景
- El表达式的引入:
- 485. Max Consecutive Ones
- JS学习之包装对象与日期对象
- BZOJ 2086--[Poi2010]Blocks【单调栈】
- HDU 4027 Can you answer these queries?(线段树单点更新+询问+神坑)
- 使用VS2013创建C#的dll文件
- halcon图像旋转
- Kotlin入门(6)条件分支的实现
- 环信接入报错解决方案
- IAR如何生成库和使用库
- EL表达式的 if else
- layer的Icon样式以及一些常用的layer窗口使用
- linux内核模块相关命令:lsmod,depmod,modprobe,modinfo,insmod,rmmod 使用说明