[UOJ#228]基础数据结构练习题
来源:互联网 发布:石家庄蓝点网络 编辑:程序博客网 时间:2024/06/06 19:06
题目大意
维护一个序列,支持三种操作
1、区间加法
2、区间开方下取整
3、查询区间和
线段树
有一道bzoj上的名为上帝造题的七分钟的题目没有加法操作。
有了我们怎么做呢?
假设一个区间所有数都相同,显然对它开方就是一个赋值标记嘛。
存在不同呢?
对于两个数a和b设a大于b。
原本它们的差是a-b
开方后差变成了
我们又知道
相当于每次把差变成比原来的开方还小了。
那就和bzoj那道差不多了。
对一个数不停开方一直开方到开方不会再产生变化只需要很少的步数。
因此对于一个区间最大值不等于最小值的情况,可以考虑暴力递归左右。
不过可以注意到两个数的差开方可能会开方到1然后也不再变化了。
因此区间的最大值和最小值只相差1时也需要讨论开方是否会使得它们的差产生变化,不产生变化的话可以直接打加法标记。
这样就可以做了。
#include<cstdio>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const int maxn=100000+10;ll mx[maxn*4],mi[maxn*4],sum[maxn*4],ad[maxn*4],st[maxn*4];int a[maxn*4];bool bz[maxn*4];int i,j,k,l,r,x,t,n,m;ll ans;int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f;}void build(int p,int l,int r){ if (l==r){ sum[p]=mx[p]=mi[p]=a[l]; return; } int mid=(l+r)/2; build(p*2,l,mid);build(p*2+1,mid+1,r); sum[p]=sum[p*2]+sum[p*2+1]; mx[p]=max(mx[p*2],mx[p*2+1]); mi[p]=min(mi[p*2],mi[p*2+1]);}void markst(int p,int l,int r,ll v){ ad[p]=0; mx[p]=mi[p]=v; sum[p]=(ll)(r-l+1)*v; bz[p]=1; st[p]=v;}void markad(int p,int l,int r,ll v){ ad[p]+=v; mx[p]+=v; mi[p]+=v; sum[p]+=(ll)(r-l+1)*v;}void down(int p,int l,int r){ int mid=(l+r)/2; if (bz[p]){ markst(p*2,l,mid,st[p]); markst(p*2+1,mid+1,r,st[p]); bz[p]=0; } if (ad[p]){ markad(p*2,l,mid,ad[p]); markad(p*2+1,mid+1,r,ad[p]); ad[p]=0; }}void change(int p,int l,int r,int a,int b,int v){ if (l==a&&r==b){ markad(p,l,r,v); return; } int mid=(l+r)/2; down(p,l,r); if (b<=mid) change(p*2,l,mid,a,b,v); else if (a>mid) change(p*2+1,mid+1,r,a,b,v); else{ change(p*2,l,mid,a,mid,v); change(p*2+1,mid+1,r,mid+1,b,v); } sum[p]=sum[p*2]+sum[p*2+1]; mx[p]=max(mx[p*2],mx[p*2+1]); mi[p]=min(mi[p*2],mi[p*2+1]);}void kf(int p,int l,int r,int a,int b){ if (l==a&&r==b){ if (mx[p]==mi[p]){ markst(p,l,r,int(sqrt(mx[p]))); return; } else if (mx[p]-mi[p]==1){ if (int(sqrt(mi[p]))==int(sqrt(mx[p]))) markst(p,l,r,int(sqrt(mx[p]))); else markad(p,l,r,int(sqrt(mi[p]))-mi[p]); return; } down(p,l,r); int mid=(l+r)/2; kf(p*2,l,mid,a,mid);kf(p*2+1,mid+1,r,mid+1,b); sum[p]=sum[p*2]+sum[p*2+1]; mx[p]=max(mx[p*2],mx[p*2+1]); mi[p]=min(mi[p*2],mi[p*2+1]); return; } down(p,l,r); int mid=(l+r)/2; if (b<=mid) kf(p*2,l,mid,a,b); else if (a>mid) kf(p*2+1,mid+1,r,a,b); else{ kf(p*2,l,mid,a,mid); kf(p*2+1,mid+1,r,mid+1,b); } sum[p]=sum[p*2]+sum[p*2+1]; mx[p]=max(mx[p*2],mx[p*2+1]); mi[p]=min(mi[p*2],mi[p*2+1]);}ll query(int p,int l,int r,int a,int b){ if (l==a&&r==b) return sum[p]; down(p,l,r); int mid=(l+r)/2; if (b<=mid) return query(p*2,l,mid,a,b); else if (a>mid) return query(p*2+1,mid+1,r,a,b); else return query(p*2,l,mid,a,mid)+query(p*2+1,mid+1,r,mid+1,b);}int main(){ n=read();m=read(); fo(i,1,n) a[i]=read(); build(1,1,n); while (m--){ t=read(); if (t==1){ l=read();r=read();x=read(); change(1,1,n,l,r,x); } else if (t==2){ l=read();r=read(); kf(1,1,n,l,r); } else{ l=read();r=read(); ans=query(1,1,n,l,r); printf("%lld\n",ans); } }}
0 0
- UOJ#228 基础数据结构练习题
- [UOJ#228]基础数据结构练习题
- UOJ 228 基础数据结构练习题
- 【UOJ #228】 基础数据结构练习题
- UOJ#228——基础数据结构练习题
- uoj#228. 基础数据结构练习题
- 【线段树+均摊思想】UOJ #228 基础数据结构练习题
- UOJ #228(基础数据结构练习题-区间开根+区间加+区间求和)
- [均摊 线段树] UOJ #228. 基础数据结构练习题
- [均摊 线段树] UOJ#228. 基础数据结构练习题
- 【数据结构基础]】数据库练习题
- [题解]uoj228 基础数据结构练习题
- [uoj228]基础数据结构练习题 解题报告
- 【UOJ228】基础数据结构练习题(线段树)
- 数据结构:练习题
- 数据结构练习题
- 数据结构练习题
- 基础练习题
- /dev/fb0入门练习(linux FrameBuffer)
- 北京理工大学2004年机试第二题
- WFDB 中bxb提取annotator中的数据
- [经典]RXJava给 Android 开发者的 RxJava 详解
- [Kafka]_0
- [UOJ#228]基础数据结构练习题
- sdut acm 图结构练习——BFS——从起始点到目标点的最短步数
- 绘图不可或缺的画笔Paint-滤镜篇
- openstack 管理三十四
- Leetcode 329
- 【webapp】参考网站
- [题解]bzoj1051(HAOI2006)受欢迎的牛
- poi向已经打开的excel文件写数据导致文件被清空
- YII2 Gridview 部分使用规则