bzoj3038 上帝造题的七分钟2
Description
XLk觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。
"第一分钟,X说,要有数列,于是便给定了一个正整数数列。
第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作。
第三分钟,k说,要能查询,于是便有了求一段数的和的操作。
第四分钟,彩虹喵说,要是noip难度,于是便有了数据范围。
第五分钟,诗人说,要有韵律,于是便有了时间限制和内存限制。
第六分钟,和雪说,要省点事,于是便有了保证运算过程中及最终结果均不超过64位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。"
——《上帝造题的七分钟·第二部》
所以这个神圣的任务就交给你了。
Input
第一行一个整数n,代表数列中数的个数。
第二行n个正整数,表示初始状态下数列中的数。
第三行一个整数m,表示有m次操作。
接下来m行每行三个整数k,l,r,k=0表示给[l,r]中的每个数开平方(下取整),k=1表示询问[l,r]中各个数的和。
Output
对于询问操作,每行输出一个回答。
Sample Input
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
7
6
HINT
1:对于100%的数据,1<=n<=100000,1<=l<=r<=n,数列中的数大于0,且不超过1e12。
2:数据不保证L<=R 若L>R,请自行交换L,R,谢谢!
首先,题意是给定一个数列,支持区间所有数开根号,支持区间求和
看到有区间操作又没有插入删除,很容易想到线段树
删除比较好实现,各种乱搞
但是修改用lazy tag没法做o(╯□╰)o
因为一段区间如果刚好覆盖的时候,你发现修改tot是不可行的。因为区间加减的修改值只和区间长度有关,区间每个数开根不必一定要知道区间长度,但是要知道每个数的大小。只知道区间长度显然是不行的。举个例子:告诉你区间长度为2,tot=8,要做开根号操作。你不知道它是4+4还是1+7,前者tot要改为4,后者改为3。所以一定得往下找到单个节点再修改。这样显然要T。
这个之所以难做就在于区间开根号,而注意到开根号的一个性质就是它是根号套根号,这样数字就小的很快。因为是下取整,所以当一个数是0、1的时候就不用做下去了。这样可实现了:搞一个mark标记表示区间内是不是只有0、1,显然标记是可以上传的。修改的时候如果mark=1就不用往下做下去,否则做到叶节点。这样做是可行的,因为a[i]<=10^12。拿起计算器算一下,10^12连开六次根号就是1了,所以可行。
具体看代码吧
#include<cstdio>
#include<cmath>
using namespace std;
long long a[200000];
struct trees{
int l,r,ls,rs;
long long tot;
bool push,mrk;
}tree[1000000];
inline long long read()
{
long long 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;
}
int n,m,treesize;
inline void update(int k)
{
int ls=tree[k].ls,rs=tree[k].rs;
tree[k].tot=tree[ls].tot+tree[rs].tot;
tree[k].mrk=tree[ls].mrk&&tree[rs].mrk;
}
inline void buildtree(int l,int r)
{
if (l>r) return;
int now=++treesize;
tree[now].l=l;tree[now].r=r;
if(l==r)
{
tree[now].tot=a[l];
tree[now].mrk=(a[l]==0||a[l]==1);
return;
}
int mid=(l+r)>>1;
tree[now].ls=treesize+1;
buildtree(l,mid);
tree[now].rs=treesize+1;
buildtree(mid+1,r);
update(now);
}
inline void change(int now,int l,int r)
{
if (tree[now].mrk)return;
int x=tree[now].l,y=tree[now].r;
if (x==y)
{
tree[now].tot=(long long)sqrt(tree[now].tot);
tree[now].mrk=(tree[now].tot==1||tree[now].tot==0||tree[now].mrk);
return;
}
int mid=(x+y)>>1;
if (mid>=r) change(tree[now].ls,l,r);
else if (mid<l) change(tree[now].rs,l,r);
else
{
change(tree[now].ls,l,mid);
change(tree[now].rs,mid+1,r);
}
update(now);
}
inline long long ask(int now,int l,int r)
{
int x=tree[now].l,y=tree[now].r;
if (x==l&&y==r)return tree[now].tot;
int mid=(x+y)>>1;
if (mid>=r) return ask(tree[now].ls,l,r);
else if(mid<l) return ask(tree[now].rs,l,r);
else return ask(tree[now].ls,l,mid)+ask(tree[now].rs,mid+1,r);
}
int main()
{
n=read();
for (int i=1;i<=n;i++) a[i]=read();
buildtree(1,n);
m=read();
int opr,x,y;
for (int i=1;i<=m;i++)
{
opr=read();
x=read();
y=read();
if (y<x)
{
int t=x;
x=y;
y=t;
}
if(opr==0) change(1,x,y);
if(opr==1) printf("%lld\n",ask(1,x,y));
}
}
bzoj3038 上帝造题的七分钟2的更多相关文章
- bzoj3211花神游历各国&&bzoj3038上帝造题的七分钟2*
bzoj3211花神游历各国 题意: n个数的序列,m个操作,操作两种:区间开根(向下取整)和区间求和.n≤100000,m≤200000,序列中的数非负且≤109. 题解: 一个≤109的数开6次根 ...
- bzoj3038上帝造题的七分钟2
3038: 上帝造题的七分钟2 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1679 Solved: 713[Submit][Status][Dis ...
- Bzoj3038 上帝造题的七分钟2 线段树
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1135 Solved: 509 Description XLk觉得<上帝造题的七分钟>不太 ...
- Bzoj3038 上帝造题的七分钟2 并查集
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1135 Solved: 509 Description XLk觉得<上帝造题的七分钟>不太 ...
- TYVJ 1941 BZOJ3038 上帝造题的七分钟2 并查集+树状数组
背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段数中每个 ...
- BZOJ3038 上帝造题的七分钟
Time Limit: 3 Sec Memory Limit: 128 MB Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. "第一分钟,X说, ...
- [BZOJ3038]上帝造题的七分钟2 树状数组+并查集
考试的时候用了两个树状数组去优化,暴力修改,树状数组维护修改后区间差值还有最终求和,最后骗了40分.. 这道题有好多种做法,求和好说,最主要的是开方.这道题过的关键就是掌握一点:在数据范围内,最多开方 ...
- 【线段树】bzoj3038 上帝造题的七分钟2 / bzoj3211 花神游历各国
暴力修改,记录一段是否全部为1或0,若全是了,则不再修改. 注意3211一定要判是否为0,否则会T得惨无人道. #include<cstdio> #include<cmath> ...
- [BZOJ3211]花神游历各国&&[BZOJ3038] 上帝造题的七分钟2 树状数组+并查集
3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 4057 Solved: 1480[Submit][Status][Discu ...
随机推荐
- Javascript:阻止浏览器默认右键事件,并显示定制内容
在逛一些知名图片社区的时候,遇到自己心怡的图片,想要右键另存的时候,默认的浏览器菜单不见了,却出现了如:[©kevin版权所有]之类的信息: 今天在看Javascript事件默认行为相关的知识,所以, ...
- 【iOS基础】iOS 网络请求
一.一个HTTP请求的基本要素1.请求URL:客户端通过哪个路径找到服务器 2.请求参数:客户端发送给服务器的数据* 比如登录时需要发送的用户名和密码 3.返回结果:服务器返回给客户端的数据* 一般是 ...
- Qt 之容器内的控件全屏
m_label = new QLabel(); ui->stackedWidget->addWidget(m_label); ui->stackedWidget->setCur ...
- C#自定义List类
代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespac ...
- 台式电脑部署xen虚拟化的各种问题
本打算用一台台式机做xen虚拟化,搞了一天搞得焦头烂额还是没搞定,中间遇到各种奇葩问题,这里mark一下 1.计划用三块2TB的SATA硬盘,然后装centos5 做虚拟化,结果忘记了centos5最 ...
- .IIS7如何设置301重定向详解
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.we ...
- NHIBERNATE之映射文件配置说明(转载4)
二十.自定义值类型 开发者创建属于他们自己的值类型也是很容易的.比如说,你可能希望持久化Int64类型的属性, 持久化成为VARCHAR 字段.NHibernate没有内置这样一种类型.自定义类型 ...
- (转)asp.net动态设置标题title 关键字keywords 描述descrtptions
方法一 if (!IsPostBack){//Page title网页标题Page.Title = “我的网站标题”;//须将网页head标签设成服务器控件模式,即<head runat=&qu ...
- Create new Android Virtual Device时不能创建
在Create new Android Virtual Device时不能创建... 因为之前有重装过系统,ADT和java都没有更换,不知道是不是有哪里的环境(C盘中的配置)出错了... LOG在下 ...
- Sql省市三级联动一张表
CREATE TABLE [dbo].[region]( [region_id] [int] NULL, [region_name] [varchar](50) COLLATE Chinese_PRC ...