hdu5828 Rikka with Sequence
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5828
【题解】
考虑bzoj3211 花神游历各国,只是多了区间加操作。
考虑上题写法,区间全为1打标记。考虑推广到这题:如果一个区间max开根和min开根相同,区间覆盖标记。
巧的是,这样复杂度是错的!
e.g:
$n = 10^5, m = 10^5$
$a[] = \{1, 2, 1, 2, ... , 1, 2\}$
$operation = \{ "1~1~n~2", "2~1~n", "1~1~n~2", "2~1~n", ... \}$
然后发现没有可以合并的,每次都要暴力做,复杂度就错了。
考虑对于区间的$max-min \leq 1$的情况维护:
当$max=min$,显然直接做即可。
当$max=min+1$,如果$\sqrt{max} = \sqrt{min}$,那么变成区间覆盖;否则$\sqrt{max} = \sqrt{min} + 1$,变成区间加法。
都是线段树基本操作,所以可以做。
下面证明复杂度为什么是对的:
时间复杂度$O(nlog^2n)$。
# include <math.h>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> # ifdef WIN32
# define LLFORMAT "%I64d"
# else
# define LLFORMAT "%lld"
# endif using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 1e5 + ;
const int mod = 1e9+; inline int getint() {
int x = ; char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x<<) + (x<<) + ch - '', ch = getchar();
return x;
} int n, a[N]; const int SN = + ;
struct SMT {
ll mx[SN], mi[SN], s[SN], tag[SN], cov[SN];
# define ls (x<<)
# define rs (x<<|)
inline void up(int x) {
mx[x] = max(mx[ls], mx[rs]);
mi[x] = min(mi[ls], mi[rs]);
s[x] = s[ls] + s[rs];
}
inline void pushtag(int x, int l, int r, ll tg) {
mx[x] += tg, mi[x] += tg;
s[x] += tg * (r-l+); tag[x] += tg;
}
inline void pushcov(int x, int l, int r, ll cv) {
mx[x] = cv, mi[x] = cv;
s[x] = cv * (r-l+); cov[x] = cv; tag[x] = ;
}
inline void down(int x, int l, int r) {
register int mid = l+r>>;
if(cov[x]) {
pushcov(ls, l, mid, cov[x]);
pushcov(rs, mid+, r, cov[x]);
cov[x] = ;
}
if(tag[x]) {
pushtag(ls, l, mid, tag[x]);
pushtag(rs, mid+, r, tag[x]);
tag[x] = ;
}
}
inline void build(int x, int l, int r) {
tag[x] = cov[x] = ;
if(l == r) {
mx[x] = mi[x] = s[x] = a[l];
return ;
}
int mid = l+r>>;
build(ls, l, mid); build(rs, mid+, r);
up(x);
}
inline void edt(int x, int l, int r, int L, int R, int d) {
if(L <= l && r <= R) {
pushtag(x, l, r, d);
return ;
}
down(x, l, r);
int mid = l+r>>;
if(L <= mid) edt(ls, l, mid, L, R, d);
if(R > mid) edt(rs, mid+, r, L, R, d);
up(x);
}
inline void doit(int x, int l, int r) {
if(mx[x] == mi[x]) {
register ll t = mx[x];
pushtag(x, l, r, ll(sqrt(t)) - t);
return ;
}
if(mx[x] == mi[x] + ) {
register ll pmx = ll(sqrt(mx[x])), pmi = ll(sqrt(mi[x]));
if(pmx == pmi) pushcov(x, l, r, pmx);
else pushtag(x, l, r, pmx - mx[x]); // mx[x] = mi[x] + 1
return ;
}
down(x, l, r);
int mid = l+r>>;
doit(ls, l, mid); doit(rs, mid+, r);
up(x);
} inline void edt(int x, int l, int r, int L, int R) {
if(L <= l && r <= R) {
doit(x, l, r);
return ;
}
down(x, l, r);
int mid = l+r>>;
if(L <= mid) edt(ls, l, mid, L, R);
if(R > mid) edt(rs, mid+, r, L, R);
up(x);
} inline ll sum(int x, int l, int r, int L, int R) {
if(L <= l && r <= R) return s[x];
down(x, l, r);
int mid = l+r>>; ll ret = ;
if(L <= mid) ret += sum(ls, l, mid, L, R);
if(R > mid) ret += sum(rs, mid+, r, L, R);
return ret;
}
}T; inline void sol() {
n = getint(); register int Q = getint(), op, l, r, x;
for (int i=; i<=n; ++i) a[i] = getint();
T.build(, , n);
while(Q--) {
op = getint(), l = getint(), r = getint();
if(op == ) {
x = getint();
T.edt(, , n, l, r, x);
} else if(op == ) T.edt(, , n, l, r);
else printf(LLFORMAT "\n", T.sum(, , n, l, r));
}
} int main() {
int T = getint();
while(T--) sol();
return ;
}
hdu5828 Rikka with Sequence的更多相关文章
- HDU5828 Rikka with Sequence 线段树
分析:这个题和bc round 73应该是差不多的题,当时是zimpha巨出的,那个是取phi,这个是开根 吐槽:赛场上写的时候直接维护数值相同的区间,然后1A,结果赛后糖教一组数据给hack了,仰慕 ...
- 2018.07.23 hdu5828 Rikka with Sequence(线段树)
传送门 这道题维护区间加,区间开根,区间求和. 线段树常规操作. 首先回忆两道简单得多的线段树. 第一个:区间覆盖,区间加,区间求和. 第二个:区间开根,区间求和. 这两个是名副其实的常规操作. 但这 ...
- 2016暑假多校联合---Rikka with Sequence (线段树)
2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...
- 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence
// 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...
- HDU 5828 Rikka with Sequence (线段树)
Rikka with Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- hdu 5828 Rikka with Sequence 线段树
Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- hdu 5204 Rikka with sequence 智商不够系列
Rikka with sequence Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...
- HDU 5828 Rikka with Sequence(线段树 开根号)
Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
随机推荐
- Python 循环语句和运算符
while 循环 while 条件 : //条件为True时,执行while下带有缩进的语句 语句1 语句2 语句3 for循环 for循环可以用来遍历某一对象(遍历:通俗点说,就是把这个循环中的第一 ...
- Spring管理事务默认回滚的异常
一.默认方式 Spring的事务管理默认只对出现运行期异常(java.lang.RuntimeException及其子类),Error进行回滚. 如果一个方法抛出Exception或者Checked异 ...
- 在用js拼接html时,给元素加不上事件的问题
问题描述:有时,发起ajax请求成功后,需要用js去拼接一小段html字符串,然后给某些元素添加事件时,事件总是加不上. 解决办法:在success 回调函数内,给元素添加事件绑定. 代码如下: $. ...
- 软工实践原型设计——PaperRepositories
软工实践原型设计--PaperRepositories 写在前面 本次作业链接 队友(031602237吴杰婷)博客链接 pdf文件地址 原型设计地址(加载有点慢...) 结对成员:031602237 ...
- ubuntu 只有客人会话登录(第一次深刻感受文件权限的威力 )
为了测试docker的挂载权限,把宿主机的/etc/passwd文件挂载到了虚机当中,进入虚机想看下能不能直接对我宿主机上的文件进行操作,把/etc/passwd删掉了最后十行...结果宿主机上的/e ...
- Redis Cluster实现原理
一.Redis Cluster主要特性和设计 集群目标 1)高性能和线性扩展,最大可以支撑到1000个节点:Cluster架构中无Proxy层,Master与slave之间使用异步replic ...
- linux 装redmine
看第一篇 https://www.cnblogs.com/iluzhiyong/p/redmine.html 看第二篇 http://blog.51yip.com/cloud/1874.html 基本 ...
- asp.net中缓存的使用
刚学到asp.net怎么缓存,这里推荐学习一下 www.cnblogs.com/wang726zq/archive/2012/09/06/cache.html http://blog.csdn.net ...
- hdu 2151 Worm (DP)
Worm Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 项目管理---git----快速使用git笔记(三)------coding.net注册和新建项目(远程仓库)
我们在第一章已经了解了github和coding.net的区别: github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开. codin ...