内存限制:256 MiB时间限制:500 ms标准输入输出
题目类型:传统评测方式:文本比较
上传者: hzwer

题目描述

给出一个长为 nn 的数列 a_1\ldots a_na1​…an​,以及 nn 个操作,操作涉及区间开方,区间求和。

输入格式

第一行输入一个数字 nn。

第二行输入 nn 个数字,第 ii 个数字为 a_iai​,以空格隔开。

接下来输入 nn 行询问,每行输入四个数字 \mathrm{opt}, l, r, copt,l,r,c,以空格隔开。

若 \mathrm{opt} = 0opt=0,表示将位于 [l, r][l,r] 的之间的数字都开方。对于区间中每个 a_i(l\le i\le r),\: a_i ← \left\lfloor \sqrt{a_i}\right\rfloorai​(l≤i≤r),ai​←⌊ai​​⌋

若 \mathrm{opt} = 1opt=1,表示询问位于 [l, r][l,r] 的所有数字的和。

输出格式

对于每次询问,输出一行一个数字表示答案。

样例

样例输入

4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4

样例输出

6
2

数据范围与提示

对于 100\%100% 的数据,1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、\mathrm{ans} \leq 2^{31}-1ans≤231−1。

代码一:

 //#6281. 数列分块入门 5-区间开方,区间求和
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e4+; int n,m,pos[maxn],tag[maxn];
ll a[maxn],b[maxn]; void rechange(int x)
{
int flag=;
for(int i=(x-)*m+;i<=min(x*m,n);i++){
if(a[i]>) flag=;
}
if(!flag) tag[x]=;
} void update(int l,int r)
{
if(pos[l]==pos[r]){
if(tag[pos[l]]){
for(int i=l;i<=r;i++){
b[pos[l]]-=a[i];
a[i]=floor(sqrt(a[i]));
b[pos[l]]+=a[i];
}
rechange(pos[l]);
}
}
else{
if(tag[pos[l]]){
for(int i=l;i<=pos[l]*m;i++){
b[pos[l]]-=a[i];
a[i]=floor(sqrt(a[i]));
b[pos[l]]+=a[i];
}
rechange(pos[l]);
}
for(int i=pos[l]+;i<pos[r];i++){
if(!tag[i]) continue;
for(int j=(i-)*m+;j<=i*m;j++){
b[i]-=a[j];
a[j]=floor(sqrt(a[j]));
b[i]+=a[j];
}
rechange(i);
}
if(tag[pos[r]]){
for(int i=(pos[r]-)*m+;i<=r;i++){
b[pos[r]]-=a[i];
a[i]=floor(sqrt(a[i]));
b[pos[r]]+=a[i];
}
rechange(pos[r]);
}
}
} ll query(int l,int r)
{
ll ans=;
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++){
ans+=a[i];
}
}
else{
for(int i=l;i<=pos[l]*m;i++){
ans+=a[i];
}
for(int i=pos[l]+;i<pos[r];i++){
ans+=b[i];
}
for(int i=(pos[r]-)*m+;i<=r;i++){
ans+=a[i];
}
}
return ans;
} int main()
{
scanf("%d",&n);
m=sqrt(n);
for(int i=;i<=n;i++){
scanf("%lld",&a[i]);
pos[i]=(i-)/m+;
}
for(int i=;i<=n;i++){
int cnt=log(a[i])/log();
if(cnt>=) tag[pos[i]]=;
}
for(int i=;i<=m+;i++){
ll cnt=;
for(int j=(i-)*m+;j<=min(i*m,n);j++){
cnt+=a[j];
}
b[i]=cnt;
}
for(int i=;i<=n;i++){
int op,l,r,c;
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op==){
update(l,r);
}
else{
printf("%lld\n",query(l,r));
}
}
} /*
10
1 3 4 2 5 7 11 3 5 1
0 1 5 1
1 1 7 2
0 3 9 1
1 4 8 7
1 1 10 6
1 3 5 3
1 5 10 7
1 6 10 6
1 2 7 4
1 3 7 5 25
8
14
3
10
9
9
8
*/

代码二:

 //#6281. 数列分块入门 5-区间开方,区间求和(忘注释掉了,导致超时+wa,蠢死了)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e4+; int n,m,pos[maxn],tag[maxn];
ll a[maxn],b[maxn]; void rechange(int x)
{
ll cnt=;int flag=;
for(int i=(x-)*m+;i<=min(x*m,n);i++){
cnt+=a[i];
if(a[i]>=) flag=;
}
b[x]=cnt;
if(!flag) tag[x]=;
} void update(int l,int r)
{
if(pos[l]==pos[r]){
if(tag[pos[l]]){
for(int i=l;i<=r;i++){
a[i]=floor(sqrt(a[i]));
}
rechange(pos[l]);
}
}
else{
if(tag[pos[l]]){
for(int i=l;i<=pos[l]*m;i++){
a[i]=floor(sqrt(a[i]));
}
rechange(pos[l]);
}
for(int i=pos[l]+;i<pos[r];i++){
if(!tag[i]) continue;
for(int j=(i-)*m+;j<=i*m;j++){
a[j]=floor(sqrt(a[j]));
}
rechange(i);
}
if(tag[pos[r]]){
for(int i=(pos[r]-)*m+;i<=r;i++){
a[i]=floor(sqrt(a[i]));
}
rechange(pos[r]);
}
}
} ll query(int l,int r)
{
ll ans=;
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++){
ans+=a[i];
}
}
else{
for(int i=l;i<=pos[l]*m;i++){
ans+=a[i];
}
for(int i=pos[l]+;i<pos[r];i++){
ans+=b[i];
}
for(int i=(pos[r]-)*m+;i<=r;i++){
ans+=a[i];
}
}
//cout<<"ans: "<<ans<<endl;
return ans;
} int main()
{
scanf("%d",&n);
m=sqrt(n);
for(int i=;i<=n;i++){
scanf("%lld",&a[i]);
pos[i]=(i-)/m+;
}
for(int i=;i<=n;i++){
int cnt=log(a[i])/log();
if(cnt>=) tag[pos[i]]=;
}
for(int i=;i<=m+;i++){
ll cnt=;
for(int j=(i-)*m+;j<=min(i*m,n);j++){
cnt+=a[j];
}
b[i]=cnt;
}
for(int i=;i<=n;i++){
int op,l,r,c;
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op==){
update(l,r);
// for(int i=1;i<=n;i++)
// cout<<a[i]<<" ";
// cout<<endl;
}
else{
printf("%lld\n",query(l,r));
}
}
} /*
10
1 3 4 2 5 7 11 3 5 1
0 1 5 1
1 1 7 2
0 3 9 1
1 4 8 7
1 1 10 6
1 3 5 3
1 5 10 7
1 6 10 6
1 2 7 4
1 3 7 5 25
8
14
3
10
9
9
8
*/

LOJ #6281. 数列分块入门 5-分块(区间开方、区间求和)的更多相关文章

  1. 线段树 区间开方区间求和 & 区间赋值、加、查询

    本文同步发表于 https://www.zybuluo.com/Gary-Ying/note/1288518 线段树的小应用 -- 维护区间开方区间求和 题目传送门 约定: sum(i,j) 表示区间 ...

  2. LOJ 6281 数列分块入门 5

    简化版题意 给出一个长为n的数列,以及n个操作,操作涉及区间开方(每个数都向下取整),区间求和,保证所有数都为有符号32位正整数. N<=50000 Solution 首先我们先思考: 一个有符 ...

  3. LibreOJ 6281 数列分块入门 5(分块区间开方区间求和)

    题解:区间开方emmm,这马上让我想起了当时写线段树的时候,很显然,对于一个在2^31次方以内的数,开方7-8次就差不多变成一了,所以我们对于每次开方,如果块中的所有数都为一了,那么开方也没有必要了. ...

  4. LOJ.6281.数列分块入门5(分块 区间开方)

    题目链接 int内的数(也不非得是int)最多开方4.5次就变成1了,所以还不是1就暴力,是1就直接跳过. #include <cmath> #include <cstdio> ...

  5. [Libre 6281] 数列分块入门 5 (分块)

    水一道入门分块qwq 题面:传送门 开方基本暴力.. 如果某一个区间全部都开成1或0就打上标记全部跳过就行了 因为一个数开上个四五六次就是1了所以复杂度能过233~ code: //By Menteu ...

  6. LibreOJ 6280 数列分块入门 4(分块区间加区间求和)

    题解:分块的区间求和比起线段树来说实在是太好写了(当然,复杂度也高)但这也是没办法的事情嘛.总之50000的数据跑了75ms左右还是挺优越的. 比起单点询问来说,区间询问和也没有复杂多少,多开一个su ...

  7. LOJ.6284.数列分块入门8(分块)

    题目链接 \(Description\) 给出一个长为n的数列,以及n个操作,操作涉及区间询问等于一个数c的元素,并将这个区间的所有元素改为c. \(Solution\) 模拟一些数据可以发现,询问后 ...

  8. LibreOJ 6277 数列分块入门 1(分块)

    题解:感谢hzwer学长和loj让本蒟蒻能够找到如此合适的入门题做. 这是一道非常标准的分块模板题,本来用打标记的线段树不知道要写多少行,但是分块只有这么几行,极其高妙. 代码如下: #include ...

  9. LibreOJ 6278 数列分块入门 2(分块)

     题解:非常高妙的分块,每个块对应一个桶,桶内元素全部sort过,加值时,对于零散块O(sqrt(n))暴力修改,然后暴力重构桶.对于大块直接整块加.查询时对于非完整块O(sqrt(n))暴力遍历.对 ...

随机推荐

  1. MongoDB入门(8)- c#通过操作MongoDB GridFS实现文件的数据库存储

    GridFS介绍 GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件. GridFS GridFS长啥样 /* 1 */ { "_id" : ObjectId(& ...

  2. 2017 济南综合班 Day 2

    木棍(stick) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有很多木棍,具体的,总共有n根,且每根木棍都有一个长度.为了方便起见,我们可以用一个正 ...

  3. 数据结构&图论:图

    在这里对图的存储和遍历进行一个规范,为以后更复杂的数据结构学习打下基础 首先是邻接矩阵的形式,适合于存稠密图,如果是全连接图就再合适不过了 int a[maxn][maxn]; 一个二维数组就可以搞定 ...

  4. Linux修改用户密码

    1. root修改自己 # passwd 2. root修改别人 # passwd oracle //修改oracle的密码

  5. C11简洁之道:循环的改善

    1.  for循环的新用法 在C++98/03中,通过for循环对一个容器进行遍历,一般有两种方法,常规的for循环,或者使用<algorithm>中的for_each方法. for循环遍 ...

  6. linux shell读取配置文件

    配置文件CoverageInfo FTP_URL=ftp://svn-fb.sicent.com:21/jenkins/Jifei_Repo/OL-2/IDC_Platform/bar_seats_c ...

  7. PHP扩展--APC缓存安装与使用

    apc安装 wget http://pecl.php.net/get/APC-3.1.13.tgz tar zxvf APC-3.1.13.tgz cd APC-3.1.13 /usr/local/p ...

  8. Java应用调试利器——BTrace教程

    http://www.jianshu.com/p/26f19095d396 背景 生产环境中可能出现各种问题,但是这些问题又不是程序error导致的,可能是逻辑性错误,这时候需要获取程序运行时的数据信 ...

  9. 完全背包问题入门 (dp)

    问题描述: 有n种重量和价值分别为Wi,Vi的物品,从这些中挑选出总重量不超过W的物品,求出挑选物品的价值总和的最大值,每种物品可以挑选任意多件. 分析: 令dp[i+1][j]表示从前i件物品中挑选 ...

  10. WinRAR分割超大文件

    在自己的硬盘上有一个比较大的文件,想把它从网上通过E-Mail发送给朋友时,却发现对方的收信服务器不能够支持那么大的文件……,这时即使用ZIP等压缩软件也无济于事,因为该文件本身已经被压缩过了.于是许 ...