【uoj228】 基础数据结构练习题
http://uoj.ac/problem/228 (题目链接)
题意
给出一个序列,维护区间加法,区间开根,区间求和
Solution
线段树。考虑区间开根怎么做。当区间的最大值与最小值相等时,我们直接对整个区间开根。最坏情况下,一次开根的复杂度最坏是${O(n)}$的,然而每次开根可以迅速拉近两个数之间的大小差距,最坏复杂度的开根不会超过${5}$次。
但是考虑这样一种情况:${\sqrt{x+1}=\sqrt{x}+1}$,如果序列长成这样:${65535,65536,65535,65536······}$,那么对它开根${3}$次,每次都是最坏情况下的复杂度,最后变成了${3,4,3,4······}$,如果此时我们对它进行区间加法,又加回${65535,65536,65535,65536······}$,不断循环,复杂度就炸裂了。所以当出现这种情况时,我们也对它进行区间开根。
细节
LL
代码
// uoj228
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#define LL long long
#define inf 1ll<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=100010;
int n,m,a[maxn];
struct segtree {int l,r;LL mn,mx,tag,s;}tr[maxn<<2]; void update(int k) {
tr[k].mn=min(tr[k<<1].mn,tr[k<<1|1].mn)+tr[k].tag;
tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx)+tr[k].tag;
tr[k].s=tr[k<<1].s+tr[k<<1|1].s+tr[k].tag*(tr[k].r-tr[k].l+1);
}
void build(int k,int s,int t) {
tr[k].l=s;tr[k].r=t;
int mid=(s+t)>>1;
if (s==t) {tr[k].mn=tr[k].mx=tr[k].s=a[s];return;}
build(k<<1,s,mid);
build(k<<1|1,mid+1,t);
update(k);
}
void add(int k,int s,int t,int val) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==s && r==t) {tr[k].s+=(LL)val*(tr[k].r-tr[k].l+1);tr[k].mn+=val,tr[k].mx+=val;tr[k].tag+=val;return;}
if (t<=mid) add(k<<1,s,t,val);
else if (s>mid) add(k<<1|1,s,t,val);
else add(k<<1,s,mid,val),add(k<<1|1,mid+1,t,val);
update(k);
}
void Sqrt(int k,int s,int t,LL tag) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==s && r==t) {
if ((tr[k].mx==tr[k].mn) || (tr[k].mn+1==tr[k].mx && floor(sqrt(tr[k].mn+tag))+1==floor(sqrt(tr[k].mx+tag)))) {
LL tmp=floor(sqrt(tr[k].mn+tag))-tr[k].mn-tag;
tr[k].tag+=tmp;tr[k].mn+=tmp;tr[k].mx+=tmp;
tr[k].s+=(tr[k].r-tr[k].l+1)*tmp;
return;
}
}
if (t<=mid) Sqrt(k<<1,s,t,tag+tr[k].tag);
else if (s>mid) Sqrt(k<<1|1,s,t,tag+tr[k].tag);
else Sqrt(k<<1,s,mid,tag+tr[k].tag),Sqrt(k<<1|1,mid+1,t,tag+tr[k].tag);
update(k);
}
LL query(int k,int s,int t) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==s && r==t) return tr[k].s;
if (t<=mid) return query(k<<1,s,t)+tr[k].tag*(t-s+1);
else if (s>mid) return query(k<<1|1,s,t)+tr[k].tag*(t-s+1);
else return query(k<<1,s,mid)+query(k<<1|1,mid+1,t)+tr[k].tag*(t-s+1);
} int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
for (int op,l,r,val,i=1;i<=m;i++) {
scanf("%d%d%d",&op,&l,&r);
if (op==1) scanf("%d",&val),add(1,l,r,val);
if (op==2) Sqrt(1,l,r,0);
if (op==3) printf("%lld\n",query(1,l,r));
}
return 0;
}
【uoj228】 基础数据结构练习题的更多相关文章
- uoj228 基础数据结构练习题
趁别人题解没有放出来赶快写一篇 整数序列,操作 区间加 区间变成sqrt(下取整) 区间和 考虑一下对于每个区间里所有sqrt不同的段操作,那么可以在O(段数logn)一次的时间内完成sqrt操作.考 ...
- [UOJ228] 基础数据结构练习题 - 线段树
考虑到一个数开根号 \(loglog\) 次后就会变成1,设某个Node的势能为 \(loglog(maxv-minv)\) ,那么一次根号操作会使得势能下降 \(1\) ,一次加操作最多增加 \(l ...
- 【UOJ228】基础数据结构练习题(线段树)
[UOJ228]基础数据结构练习题(线段树) 题面 UOJ 题解 我们来看看怎么开根? 如果区间所有值都相等怎么办? 显然可以直接开根 如果\(max-sqrt(max)=min-sqrt(min)\ ...
- 【UOJ#228】基础数据结构练习题 线段树
#228. 基础数据结构练习题 题目链接:http://uoj.ac/problem/228 Solution 这题由于有区间+操作,所以和花神还是不一样的. 花神那道题,我们可以考虑每个数最多开根几 ...
- uoj #228. 基础数据结构练习题 线段树
#228. 基础数据结构练习题 统计 描述 提交 自定义测试 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的 ...
- 【线段树】uoj#228. 基础数据结构练习题
get到了标记永久化 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的好朋友九条可怜酱给她出了一道题. 给出一 ...
- UOJ228:基础数据结构练习题——题解
http://uoj.ac/problem/228 参考:https://www.cnblogs.com/ljh2000-jump/p/6357583.html 考虑当整个区间的最大值开方==最小值开 ...
- uoj228:基础数据结构练习题
题意:http://uoj.ac/problem/228 sol :线段树开根操作 对于节点x,可以在max[x]-min[x]<=1时直接做,转化为区间减或区间覆盖 #include< ...
- UOJ228 简单数据结构练习题
Description 传送门 维护一个数列, 有以下操作: 对[l,r]同时加上x 把[l,r]开根后下取整. 查询[l,r]之和 n,m \(\leq\)$ 100000, $\(a_i,x \l ...
随机推荐
- Intel 面试(就不该报外企,英语是硬伤)
1 自我介绍(用英文) 啊啊啊,能不能用中文啊,最好用英文,蒙了.... 2 你对硬件了解吗,对X86系统了解吗,知道CPU是怎么处理读一个数据的吗,说说cpu从读一个数据,到内存怎么进行处理? 说的 ...
- 使用BAPI批量修改采购信息记录的税率
业务方面提出需求:由于国家税率从5月份开始16%更改为13%.要求开发一个批量修改采购信息记录税率的功能. 税代码就是税率,J2代表13% 这个需求在ME13里面就可以单个修改,所以可以用BDC,但后 ...
- kettle学习笔记(六)——kettle转换步骤
一.概述 转换步骤分类: 1. 增加新的列 2. 字符串处理 3. 行列变换 4. 排序/排重/字段选择 5. 其他转换步骤 二.增加新的列 1.增加常量列 增加一列常量的列 其它增加列的操作大同小异 ...
- 20155238 《JAVA程序设计》实验二(Java面向对象程序设计)实验报告
实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验要求 1.没有Linux基础的同学建议先学习<L ...
- Exp7
实验内容 简单应用SET工具建立冒名网站 kali IP: 192.168.1.160 (原198) win7 IP: 192.168.1.199 1.开启本机Apache服务 (1)查看80端口是否 ...
- python 回溯法 子集树模板 系列 —— 19、野人与传教士问题
问题 在河的左岸有N个传教士.N个野人和一条船,传教士们想用这条船把所有人都运过河去,但有以下条件限制: (1)修道士和野人都会划船,但船每次最多只能运M个人: (2)在任何岸边以及船上,野人数目都不 ...
- Ubuntu 守护进程
项目中用的Qt开发的GUI程序,需要随机自启动. 最初尝试过使用SuperVisor,但是会出现下面的错误. qt.qpa.screen: QXcbConnection: Could not conn ...
- centos7 部署mysql-5.7.20
一.系统环境 系统:CentOS Linux release 7.5 mysqlb进制包:mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz 1)依赖包安装 yum ...
- Centos 7 部署Kubernetes(K8S)集群
资源链接:https://pan.baidu.com/s/1-PT_QQAf7cTu_znX-S-r9Q 密码:33sr 转发:http://blog.51cto.com/lizhenliang/19 ...
- 软件测试----H模型
H模型将测试活动完全独立出来,形成一个完整的流程,同时将测试准备和测试执行清晰表现出来. 测试流程: --测试准备:所有测试活动的准备判断是否到测试就绪点. --测试就绪点:测试准入准则,即是否可以开 ...