题目描述

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的。

代码

  1 #include <cstdio>
  2 #include <cmath>
  3
  4 #define R register
  5 #define maxn 1048586
  6 typedef long long ll;
  7 int a[maxn];
  8 ll sum[maxn], mn[maxn], mx[maxn], tag[maxn], mnnum[maxn], mxnum[maxn];
  9 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
 10 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
 11 inline void update(R int o)
 12 {
 13     sum[o] = sum[o << 1] + sum[o << 1 | 1];
 14     mn[o] = dmin(mn[o << 1], mn[o << 1 | 1]);
 15     mx[o] = dmax(mx[o << 1], mx[o << 1 | 1]);
 16 }
 17 inline void pushdown(R int o, R int l, R int r, R int mid)
 18 {
 19     if (tag[o] != 0)
 20     {
 21         sum[o << 1] += 1ll * tag[o] * (mid - l + 1);
 22         sum[o << 1 | 1] += 1ll * tag[o] * (r - mid);
 23         mn[o << 1] += tag[o]; mx[o << 1] += tag[o];
 24         mn[o << 1 | 1] += tag[o]; mx[o << 1 | 1] += tag[o];
 25         tag[o << 1] += tag[o];
 26         tag[o << 1 | 1] += tag[o];
 27         tag[o] = 0;
 28     }
 29 }
 30 void build(R int o, R int l, R int r)
 31 {
 32     if (l == r)
 33     {
 34         mn[o] = mx[o] = sum[o] = a[l];
 35         mnnum[o] = mxnum[o] = 1;
 36         return ;
 37     }
 38     R int mid = l + r >> 1;
 39     build(o << 1, l, mid);
 40     build(o << 1 | 1, mid + 1, r);
 41     update(o);
 42 }
 43 int ql, qr, qv;
 44 void modify1(R int o, R int l, R int r)
 45 {
 46     if (ql <= l && r <= qr)
 47     {
 48         tag[o] += qv;
 49         sum[o] += 1ll * qv * (r - l + 1);
 50         mx[o] += qv;
 51         mn[o] += qv;
 52         return ;
 53     }
 54     R int mid = l + r >> 1;
 55     pushdown(o, l, r, mid);
 56     if (ql <= mid) modify1(o << 1, l, mid);
 57     if (mid < qr) modify1(o << 1 | 1, mid + 1, r);
 58     update(o);
 59 }
 60 inline bool check(R ll x)
 61 {
 62     return (ll) sqrt(x) * (ll) sqrt(x) == x;
 63 }
 64 void modify2(R int o, R int l, R int r)
 65 {
 66     if (ql <= l && r <= qr)
 67     {
 68         if (mx[o] == mn[o] || (mx[o] - mn[o] == 1 && check(mx[o])))
 69         {
 70             R ll p = mx[o] - (ll) sqrt(mx[o]);
 71             tag[o] -= p;
 72             sum[o] -= p * (r - l + 1);
 73             mx[o] -= p;
 74             mn[o] -= p;
 75         }
 76         else
 77         {
 78             R int mid = l + r >> 1;
 79             pushdown(o, l, r, mid);
 80             modify2(o << 1, l, mid);
 81             modify2(o << 1 | 1, mid + 1, r);
 82             update(o);
 83         }
 84         return ;
 85     }
 86     R int mid = l + r >> 1;
 87     pushdown(o, l, r, mid);
 88     if (ql <= mid) modify2(o << 1, l, mid);
 89     if (mid < qr) modify2(o << 1 | 1, mid + 1, r);
 90     update(o);
 91 }
 92 inline ll query(R int o, R int l, R int r)
 93 {
 94     if (ql <= l && r <= qr) return sum[o];
 95     R int mid = l + r >> 1; R ll ret = 0;
 96     pushdown(o, l, r, mid);
 97     if (ql <= mid) ret += query(o << 1, l, mid);
 98     if (mid < qr) ret += query(o << 1 | 1, mid + 1, r);
 99     return ret;
100 }
101 int main()
102 {
103     R int n, m; scanf("%d%d", &n, &m);
104     for (R int i = 1; i <= n; ++i) scanf("%d", a + i);
105     build(1, 1, n);
106     for (R int i = 1; i <= m; ++i)
107     {
108         R int opt, l, r; scanf("%d%d%d", &opt, &l, &r);
109         if (opt == 1)
110         {
111             R int x; scanf("%d",  &x);
112             ql = l; qr = r; qv = x;
113             modify1(1, 1, n);
114         }
115         else if (opt == 2)
116         {
117             ql = l; qr = r;
118             modify2(1, 1, n);
119         }
120         else
121         {
122             ql = l; qr = r;
123             printf("%lld\n", query(1, 1, n));
124         }
125     }
126     return 0;
127 }

转载于:https://www.cnblogs.com/cocottt/p/7105238.html

【UOJ#228】 基础数据结构练习题相关推荐

  1. UOJ228:基础数据结构练习题——题解

    http://uoj.ac/problem/228 参考:https://www.cnblogs.com/ljh2000-jump/p/6357583.html 考虑当整个区间的最大值开方==最小值开 ...

  2. 哪里能练计算机基础知识题库,计算机基础知识练习题集锦.doc

    计算机基础知识练习题集锦.doc (22页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 24.9 积分 计算机基础知识练习题集锦全国计算机一级等级考试选 ...

  3. 计算机一级选择题必背基础知识,计算机一级考试基础知识练习题(三)

    计算机一级考试基础知识练习题(三) 一.单选题 1.第一台电子数字计算机的运算速度为每秒______. A:500000次 B:50000次 C:5000次 D:500次 答案: C 2.计算机可分为 ...

  4. 暑期集训2:ACM基础算法 练习题G:POJ - 1298

    2018学校暑期集训第二天--ACM基础算法 练习题G  --  POJ - 1298 The Hardest Problem Ever Julius Caesar lived in a time o ...

  5. 暑期集训2:ACM基础算法 练习题C:CF-1008A

    2018学校暑期集训第二天--ACM基础算法 练习题A  --   CodeForces - 1008A Romaji Vitya has just started learning Berlanes ...

  6. 暑期集训2:ACM基础算法 练习题B:CF-1008B

    2018学校暑期集训第二天--ACM基础算法 练习题B  --   CodeForces - 1008B Turn the Rectangles There are nn rectangles in ...

  7. 暑期集训2:ACM基础算法 练习题A:CF-1008C

    2018学校暑期集训第二天--ACM基础算法 练习题A  --  CodeForces - 1008C Reorder the Array You are given an array of inte ...

  8. 第一章c语言基础知识答案,第一章 C语言的基础知识练习题

    第一章 C语言的基础知识练习题 第一章 C语言的基础知识 第一节 对C语言的初步认识 习题 1. 下列叙述中错误的是 B A)任何一个C程序都必须有且仅有一个main函数,C语言总是从main函数开始 ...

  9. Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...

最新文章

  1. Microbiome:山大杜宗军团队揭示捕食性细菌新类群-慢生单胞菌目细菌独特的生境适应性...
  2. java 不同数据类型之间的转换
  3. SpringMVC拦截器与异常处理
  4. SQLServer性能优化一则小实例(2010-07-21)
  5. LeetCode面试刷题技巧-二分查找算法(下):通过 LeetCode 学习二分查找算法-销售价值减少的颜色球
  6. PHP下socket编程
  7. opencv python cv2.threshold()函数报错 TypeError: Expected cv::UMat for argument 'mat'
  8. SharePoint 2010 产品六大功能模块
  9. 201612-5 卡牌游戏
  10. input文本框自动填充背景色黄色解决办法
  11. 从数据库层面手动删除zabbix告警
  12. hacker代码_如何仅用7行R代码构建Hacker News Frontpage抓取工具
  13. ES6 数值的拓展笔记
  14. matlab--sum函数用法
  15. linux 系统命令启动,Linux开关机及系统进程命令
  16. ________________springbootのMybatis
  17. c语言编程GetTickCount,c语言计算时间方法---clock-GetTickCount-QueryPerformanceCounter
  18. Redis的集群原理
  19. java二面问什么_java面试题,拼多多面试题分享(java二面)
  20. java删除占用的文件_「强力删除」自己用命令强制删除占用的文件或文件夹 - seo实验室...

热门文章

  1. 成功解决需要Xmanager软件来处理X11转发需求
  2. CMU 15-213 CSAPP (Ch1~Ch3)
  3. 目标检测中的评估指标:PR曲线、AP、mAP
  4. 江西外语外贸官网 仿写
  5. 数学速算法_小学数学必考应用题解题思路及方法大汇总(附各年级练习题及答案)...
  6. 最给人启迪的30条编程名言
  7. L1-7 谷歌的招聘
  8. PEP 526 – Syntax for Variable Annotations
  9. Git使用教程【一】
  10. networkx 有向图强连通_有向图的强连通分支