题目描述

sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧。

在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手。于是她的好朋友九条可怜酱给她出了一道题。

给出一个长度为 nn 的数列 AA,接下来有 mm 次操作,操作有三种:

  1. 对于所有的 i∈[l,r]i∈[l,r],将 AiAi 变成 Ai+xAi+x。
  2. 对于所有的 i∈[l,r]i∈[l,r],将 AiAi 变成 ⌊Ai‾‾√⌋⌊Ai⌋。
  3. 对于所有的 i∈[l,r]i∈[l,r],询问 AiAi 的和。

作为一个不怎么熟练的初学者,sylvia 想了好久都没做出来。而可怜酱又外出旅游去了,一时间联系不上。于是她决定向你寻求帮助:你能帮她解决这个问题吗。

输入格式

第一行两个数:n,m。

接下来一行 n 个数 Ai。

接下来 m 行中,第 i 行第一个数 ti 表示操作类型:

若 ti=1,则接下来三个整数 li,ri,xi,表示操作一。

若 ti=2,则接下来三个整数 li,ri,表示操作二。

若 ti=3,则接下来三个整数 li,ri,表示操作三。

输出格式

对于每个询问操作,输出一行表示答案。

样例一

input

5 5
1 2 3 4 5
1 3 5 2
2 1 4
3 2 4
2 3 5
3 1 5

output

5
6

样例二

见样例数据下载。

限制与约定

测试点编号 n 的规模 m 的规模 其他约定
1 n≤3000 m≤3000  
2
3
4 n≤100000 m≤100000 数据随机生成
5
6 ti≠1
7
8  
9
10

对于所有数据,保证有 1≤li≤ri≤n,1≤Ai,xi≤105

时间限制:1s

空间限制:256MB

题解

orz 北大爷yyy。

用线段树维护区间的最大、最小值和答案。每次区间取根号的时候我们发现区间的极差都会减少,最后会减少到0。可以证明这个次数是loglogn级别的(开根相当于指数一直除以2),所以可以暴力递归进去改。但是区间加会导致区间的极差发生变化也有可能不变。所以我们在做开根号的时候只有在区间的极差会变的情况下我们暴力递归进去改,否则就直接区间减。可以证明这样的复杂度是NlogNloglogN的。

代码

 #include <cstdio>
#include <cmath> #define R register
#define maxn 1048586
typedef long long ll;
int a[maxn];
ll sum[maxn], mn[maxn], mx[maxn], tag[maxn], mnnum[maxn], mxnum[maxn];
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
inline void update(R int o)
{
sum[o] = sum[o << ] + sum[o << | ];
mn[o] = dmin(mn[o << ], mn[o << | ]);
mx[o] = dmax(mx[o << ], mx[o << | ]);
}
inline void pushdown(R int o, R int l, R int r, R int mid)
{
if (tag[o] != )
{
sum[o << ] += 1ll * tag[o] * (mid - l + );
sum[o << | ] += 1ll * tag[o] * (r - mid);
mn[o << ] += tag[o]; mx[o << ] += tag[o];
mn[o << | ] += tag[o]; mx[o << | ] += tag[o];
tag[o << ] += tag[o];
tag[o << | ] += tag[o];
tag[o] = ;
}
}
void build(R int o, R int l, R int r)
{
if (l == r)
{
mn[o] = mx[o] = sum[o] = a[l];
mnnum[o] = mxnum[o] = ;
return ;
}
R int mid = l + r >> ;
build(o << , l, mid);
build(o << | , mid + , r);
update(o);
}
int ql, qr, qv;
void modify1(R int o, R int l, R int r)
{
if (ql <= l && r <= qr)
{
tag[o] += qv;
sum[o] += 1ll * qv * (r - l + );
mx[o] += qv;
mn[o] += qv;
return ;
}
R int mid = l + r >> ;
pushdown(o, l, r, mid);
if (ql <= mid) modify1(o << , l, mid);
if (mid < qr) modify1(o << | , mid + , r);
update(o);
}
inline bool check(R ll x)
{
return (ll) sqrt(x) * (ll) sqrt(x) == x;
}
void modify2(R int o, R int l, R int r)
{
if (ql <= l && r <= qr)
{
if (mx[o] == mn[o] || (mx[o] - mn[o] == && check(mx[o])))
{
R ll p = mx[o] - (ll) sqrt(mx[o]);
tag[o] -= p;
sum[o] -= p * (r - l + );
mx[o] -= p;
mn[o] -= p;
}
else
{
R int mid = l + r >> ;
pushdown(o, l, r, mid);
modify2(o << , l, mid);
modify2(o << | , mid + , r);
update(o);
}
return ;
}
R int mid = l + r >> ;
pushdown(o, l, r, mid);
if (ql <= mid) modify2(o << , l, mid);
if (mid < qr) modify2(o << | , mid + , r);
update(o);
}
inline ll query(R int o, R int l, R int r)
{
if (ql <= l && r <= qr) return sum[o];
R int mid = l + r >> ; R ll ret = ;
pushdown(o, l, r, mid);
if (ql <= mid) ret += query(o << , l, mid);
if (mid < qr) ret += query(o << | , mid + , r);
return ret;
}
int main()
{
R int n, m; scanf("%d%d", &n, &m);
for (R int i = ; i <= n; ++i) scanf("%d", a + i);
build(, , n);
for (R int i = ; i <= m; ++i)
{
R int opt, l, r; scanf("%d%d%d", &opt, &l, &r);
if (opt == )
{
R int x; scanf("%d", &x);
ql = l; qr = r; qv = x;
modify1(, , n);
}
else if (opt == )
{
ql = l; qr = r;
modify2(, , n);
}
else
{
ql = l; qr = r;
printf("%lld\n", query(, , n));
}
}
return ;
}

【UOJ#228】 基础数据结构练习题的更多相关文章

  1. 【线段树】uoj#228. 基础数据结构练习题

    get到了标记永久化 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的好朋友九条可怜酱给她出了一道题. 给出一 ...

  2. uoj #228. 基础数据结构练习题 线段树

    #228. 基础数据结构练习题 统计 描述 提交 自定义测试 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的 ...

  3. uoj#228 基础数据结构练习题

    题面:http://uoj.ac/problem/228 正解:线段树. 我们可以发现,开根号时一个区间中的数总是趋近相等.判断一个区间的数是否相等,只要判断最大值和最小值是否相等就行了.如果这个区间 ...

  4. uoj#228. 基础数据结构练习题(线段树区间开方)

    题目链接:http://uoj.ac/problem/228 代码:(先开个坑在这个地方) #include<bits/stdc++.h> using namespace std; ; l ...

  5. uoj#228. 基础数据结构练习题(线段树)

    传送门 只有区间加区间开方我都会--然而加在一起我就gg了-- 然后这题的做法就是对于区间加直接打标记,对于区间开方,如果这个区间的最大值等于最小值就直接区间覆盖(据ljh_2000大佬说这个区间覆盖 ...

  6. UOJ #228. 基础数据结构练习题 线段树 + 均摊分析 + 神题

    题目链接 一个数被开方 #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",st ...

  7. UOJ #228 - 基础数据结构练习题(势能线段树+复杂度分析)

    题面传送门 神仙题. 乍一看和经典题 花神游历各国有一点像,只不过多了一个区间加操作.不过多了这个区间加操作就无法再像花神游历各国那样暴力开根直到最小值为 \(1\) 为止的做法了,稍微感性理解一下即 ...

  8. 【UOJ#228】基础数据结构练习题 线段树

    #228. 基础数据结构练习题 题目链接:http://uoj.ac/problem/228 Solution 这题由于有区间+操作,所以和花神还是不一样的. 花神那道题,我们可以考虑每个数最多开根几 ...

  9. 【UOJ228】基础数据结构练习题(线段树)

    [UOJ228]基础数据结构练习题(线段树) 题面 UOJ 题解 我们来看看怎么开根? 如果区间所有值都相等怎么办? 显然可以直接开根 如果\(max-sqrt(max)=min-sqrt(min)\ ...

随机推荐

  1. Ruby Rails学习中:关于测试的补充,MiniTest报告程序,Guard自动测试

    一. 关于测试的补充 1.MiniTest报告程序 为了让 Rails 应用的测试适时显示红色和绿色,我建议你在测试辅助文件中加入以下内容: (1).打开文件:test/test_helper.rb ...

  2. Fiddler之常用操作(过滤器设置,代理设置,手机抓包设置,手机代理配置)

    记录下,工作中常用的一些设置和操作~ 1.过滤“脏”请求 两个下拉框的名词解释: A.内外网过滤 No Zone Filter:不分区域过滤(内网外网都显示) Show only Intranet H ...

  3. 阿里云自动获取token值(python)

    一,token说明 token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识.当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个 ...

  4. 移动端真机debug调试神器 vConsole学习(一)之基础

    参考 使用方法 移动端真机debug调试神器 vConsole的引入说明(原生态与WebPack) 移动端使用vconsole调试console vConsole ——开源的前端 console 调试 ...

  5. oracle数据库锁的问题

    查询当前数据库被锁的对象 select b.owner,b.object_name,a.SESSION_ID,a.LOCKED_MODE from v$locked_object a dba_obje ...

  6. 分库分布的几件小事(四)分库分表的id主键生成

    1.问题 其实这是分库分表之后你必然要面对的一个问题,就是id咋生成?因为要是分成多个表之后,每个表都是从1开始累加,那肯定不对啊,需要一个全局唯一的id来支持.所以这都是你实际生产环境中必须考虑的问 ...

  7. java启动server时报端口无效解决方法

    今天在Java里配置Tomcat服务器,启动时出现如下图报错信息 The server cannot be started because one or more of the ports are i ...

  8. jeesite 跳开登录页面直接访问

    把控制层的${adminPath}改为${frontPath} 访问时吧/a改为/f 也可以在jeesite配置文件内配置两个的值 http://localhost:8181/cxfvp/a?logi ...

  9. golang实现RSA加密解密

    非对称加密示意图: 在此可以看到,非对称加密是通过两个密钥(公钥-私钥)来实现对数据的加密和解密的.公钥用于加密,私钥用于解密. RSA公钥和私钥生成: package main import ( & ...

  10. AxMath_V2.5.0.0安装和激活

    目录 1. 相关推荐 2. 按 3. AxMath 功能与特色 4. 软件介绍 4.1. 编辑与排版 4.2. 科学计算功能 4.3. 输出与发布 4.4. 运行环境 4.5. 破解说明 5. 安装步 ...