HDU 4027 Can you answer these queries?(线段树)
2016-01-05 14:00
435 查看
Description
给出n个数,m次操作,操作有两种:
1.0 a b:将区间[a,b]中的所有数都开更号(向下取整)
2.1 a b:查询区间[a,b]中元素之和
Input
第一行为一整数n表示序列长度,第二行n个整数ai表示这个序列,第三行为一整数m表示操作数,之后m行每行三个整数表示一次操作
(1<=n,m<=100000,0< ai<=2^63)
Output
对于每次询问,输出查询结果
Sample Input
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
Sample Output
Case #1:
19
7
6
Solution
一个不大于2^63的整数至多经过6次开更号就会变成1,所以就算所有点都更新复杂度也不会超过O(6*n),因此在用线段树维护区间和的时候,如果一个区间的和已经等于这个区间的长度,那么就不用往下继续更新了,因为这时候区间所有元素都已经是1了
Code
给出n个数,m次操作,操作有两种:
1.0 a b:将区间[a,b]中的所有数都开更号(向下取整)
2.1 a b:查询区间[a,b]中元素之和
Input
第一行为一整数n表示序列长度,第二行n个整数ai表示这个序列,第三行为一整数m表示操作数,之后m行每行三个整数表示一次操作
(1<=n,m<=100000,0< ai<=2^63)
Output
对于每次询问,输出查询结果
Sample Input
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
Sample Output
Case #1:
19
7
6
Solution
一个不大于2^63的整数至多经过6次开更号就会变成1,所以就算所有点都更新复杂度也不会超过O(6*n),因此在用线段树维护区间和的时候,如果一个区间的和已经等于这个区间的长度,那么就不用往下继续更新了,因为这时候区间所有元素都已经是1了
Code
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; #define maxn 111111 struct Tree { int left,right; ll sum; }T[4*maxn]; void push_up(int t) { T[t].sum=T[2*t].sum+T[2*t+1].sum; } void build(int l,int r,int t) { T[t].left=l; T[t].right=r; if(l==r) { scanf("%lld",&T[t].sum); return ; } int mid=(l+r)>>1; build(l,mid,2*t); build(mid+1,r,2*t+1); push_up(t); } void update(int l,int r,int t) { if(T[t].left==T[t].right) { T[t].sum=sqrt(1.0*T[t].sum); return ; } if(T[t].left==l&&T[t].right==r&&T[t].sum==r-l+1)return ; int mid=(T[t].left+T[t].right)>>1; if(r<=mid)update(l,r,2*t); else if(l>mid)update(l,r,2*t+1); else { update(l,mid,2*t); update(mid+1,r,2*t+1); } push_up(t); } ll query(int l,int r,int t) { if(T[t].left==l&&T[t].right==r)return T[t].sum; int mid=(T[t].left+T[t].right)>>1; if(r<=mid)return query(l,r,2*t); if(l>mid)return query(l,r,2*t+1); return query(l,mid,2*t)+query(mid+1,r,2*t+1); } int main() { int n,m,res=1; while(~scanf("%d",&n)) { build(1,n,1); scanf("%d",&m); printf("Case #%d:\n",res++); while(m--) { int op,a,b; scanf("%d%d%d",&op,&a,&b); if(a>b)swap(a,b); if(op==0) update(a,b,1); else printf("%lld\n",query(a,b,1)); } printf("\n"); } return 0; }
相关文章推荐
- UISearchBar光标偏移设置
- break与continue区别
- 让UI失业的网站,各种安卓常用图标。
- IOS开发UI篇--YXFilmSelectView(一个酷炫的电影选票View)
- 修改ligerui 默认确认按钮
- 基于Android 下载文件时,更新UI简单帮助类
- suid和sgid的个人理解
- 【UI布局优化】Hierarchy Viewer-优化你的UI
- Hbuilder的mui
- 构建本地yum源之rpmbuild
- UGUI源码调试
- android-运用notifyDataSetChanged()更新UI
- UIAlertController在ios8的使用
- Zoho Recruit推出手机版
- 检测到有潜在危险的 Request.Form 值
- leetcode: Unique Paths II
- UIlabel 富文本
- Android UI控件的分类
- iOS9UICollectionView自定义布局modifying attributes returned by UICollectionViewFlowLayout without copying them
- UITableViewCell的separator分隔线设置失效