2018.07.23 hdu5828 Rikka with Sequence(线段树)
传送门
这道题维护区间加,区间开根,区间求和。
线段树常规操作。
首先回忆两道简单得多的线段树。
第一个:区间覆盖,区间加,区间求和。
第二个:区间开根,区间求和。
这两个是名副其实的常规操作。
但这道题如果学习没有区间加的做法维护最大值很容易卡掉。
所以怎么做呢?
区间加和区间求和就略了。
考虑到开根的性质,显然一段区间的数多开几次根差就不大了。
这样的话,我们维护区间最大值和区间最小值,如果当前区间的最大值与最小值的差不大于1的话就直接进行开根操作,否则继续递归。
开根时要分类讨论。
我们令fx=sqrt(max)" role="presentation" style="position: relative;">fx=sqrt(max)fx=sqrt(max),fy=sqrt(min)" role="presentation" style="position: relative;">fy=sqrt(min)fy=sqrt(min),就有两种情况。
第一种:fx==fy" role="presentation" style="position: relative;">fx==fyfx==fy,那么这相当于区间覆盖。
第二种:fx==fy+1" role="presentation" style="position: relative;">fx==fy+1fx==fy+1,那么显然有max−min==1" role="presentation" style="position: relative;">max−min==1max−min==1,所以推出max−fx==min−fy" role="presentation" style="position: relative;">max−fx==min−fymax−fx==min−fy,所以就成了一个区间加操作(只是加了一个非负数)。这就转化成了第一个基础线段树的操作了。
代码如下:
#include<bits/stdc++.h>
#include<bits/stdc++.h>
#define N 100005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define ll long long
using namespace std;
inline ll read(){
ll ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
inline void write(ll x){
if(x>9)write(x/10);
putchar((x%10)^48);
}
int n,m,T_T;
ll a[N];
inline ll max(ll a,ll b){return a>b?a:b;}
inline ll min(ll a,ll b){return a<b?a:b;}
struct Node{int l,r;ll maxn,minn,sum,lz,bz;}T[N<<2];
inline void pushup(int p){T[p].maxn=max(T[lc].maxn,T[rc].maxn),T[p].minn=min(T[lc].minn,T[rc].minn),T[p].sum=T[lc].sum+T[rc].sum;}
inline void pushnow(int p,ll v){T[p].sum+=(T[p].r-T[p].l+1)*v,T[p].lz+=v,T[p].maxn+=v,T[p].minn+=v;}
inline void pushnown(int p,ll v){T[p].lz=0;T[p].sum=(T[p].r-T[p].l+1)*v,T[p].bz=T[p].maxn=T[p].minn=v;}
inline void pushdown(int p){
if(T[p].bz!=-1)pushnown(lc,T[p].bz),pushnown(rc,T[p].bz),T[p].bz=-1;
if(T[p].lz)pushnow(lc,T[p].lz),pushnow(rc,T[p].lz),T[p].lz=0;
}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r,T[p].lz=0,T[p].bz=-1;
if(l==r){T[p].maxn=T[p].minn=T[p].sum=a[l];return;}
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,ll v){
if(ql>T[p].r||qr<T[p].l)return;
if(ql<=T[p].l&&T[p].r<=qr){pushnow(p,v);return;}
pushdown(p);
if(qr<=mid)update(lc,ql,qr,v);
else if(ql>mid)update(rc,ql,qr,v);
else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
pushup(p);
}
inline void modify(int p,int ql,int qr){
if(ql>T[p].r||qr<T[p].l)return;
if(ql<=T[p].l&&T[p].r<=qr&&T[p].maxn-T[p].minn<=1){
ll fx=sqrt(T[p].maxn),fy=sqrt(T[p].minn);
if(fx==fy)pushnown(p,fx);
else pushnow(p,fx-T[p].maxn);
return;
}
pushdown(p);
if(qr<=mid)modify(lc,ql,qr);
else if(ql>mid)modify(rc,ql,qr);
else modify(lc,ql,mid),modify(rc,mid+1,qr);
pushup(p);
}
inline ll query(int p,int ql,int qr){
if(ql>T[p].r||qr<T[p].l)return 0;
if(ql<=T[p].l&&T[p].r<=qr)return T[p].sum;
pushdown(p);
if(qr<=mid)return query(lc,ql,qr);
if(ql>mid)return query(rc,ql,qr);
return query(lc,ql,mid)+query(rc,mid+1,qr);
}
int main(){
T_T=read();
while(T_T--){
n=read(),m=read();
for(int i=1;i<=n;++i)a[i]=read();
build(1,1,n);
while(m--){
int op=read(),l=read(),r=read();
switch(op){
case 1:{ll v=read();update(1,l,r,v);break;}
case 2:{modify(1,l,r);break;}
default:{write(query(1,l,r)),puts("");break;}
}
}
}
return 0;
}
2018.07.23 hdu5828 Rikka with Sequence(线段树)的更多相关文章
- HDU5828 Rikka with Sequence 线段树
分析:这个题和bc round 73应该是差不多的题,当时是zimpha巨出的,那个是取phi,这个是开根 吐槽:赛场上写的时候直接维护数值相同的区间,然后1A,结果赛后糖教一组数据给hack了,仰慕 ...
- 2016暑假多校联合---Rikka with Sequence (线段树)
2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...
- hdu 5828 Rikka with Sequence 线段树
Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- 2018.07.08 hdu6183 Color it(线段树)
Color it Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Proble ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- HDU 5828 Rikka with Sequence (线段树+剪枝优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...
- 2018.07.08 POJ 2481 Cows(线段树)
Cows Time Limit: 3000MS Memory Limit: 65536K Description Farmer John's cows have discovered that the ...
- HDU5634 Rikka with Phi 线段树
// HDU5634 Rikka with Phi 线段树 // 思路:操作1的时候,判断一下当前区间是不是每个数都相等,在每个数相等的区间上操作.相当于lazy,不必更新到底. #include & ...
- 2018.07.23 codeforces 438D. The Child and Sequence(线段树)
传送门 线段树维护区间取模,单点修改,区间求和. 这题老套路了,对一个数来说,每次取模至少让它减少一半,这样每次单点修改对时间复杂度的贡献就是一个log" role="presen ...
随机推荐
- Laravel之Eloquent ORM
一.ORM编程思想 1.1 Active Record 设计模式 Active Record 是一种数据访问设计模式,它可以帮助你实现数据对象Object到关系数据库的映射.应用Active Reco ...
- RabbitMQ Window环境安装
转自:https://www.cnblogs.com/zzpblogs/p/8168763.html RabbitMQ环境的安装分别介绍在Window和Linux下两个环境的安装过程. Windo ...
- 前端-CSS-4-伪类选择器&伪元素选择器
1.伪类选择器(爱恨原则) -------------------------------------------------------------------------------------- ...
- MM-库存表
常用的库存价值表有: 典型T-code实际上是从不同table读数据: MMBE: MARD-LABST(Valuated stock withunrestricted use) MB52: MAR ...
- centos7 jenkins 安装
前提: 安装了 jdk ,我的是jdk8 第一步: https://jenkins.io/download/ 下载 可以下载 rpm文件, 标红处, 也可以下载war包(Generic Java pa ...
- Nginx 反向代理、后端检测模块
简介: Nginx 反向代理模块:ngx_http_proxy_module.ngx_http_upstream_module 后端检测模块:nginx_http_upstream_check_mod ...
- unity 加载读取外部XML
cfg.xml <rootNode> <category name="网站"> <item name="mainPage"> ...
- 概率论与数理统计 Q&A:
--------------------------------- 大数定律:大量样本数据的均值(样本值之和除以样本个数),近似于随机变量的期望(标准概率*样本次数).(样本(部分)趋近于总体)中心极 ...
- Java学习 第二节
1.非递归求第四十个斐波那契数 package test; public class fibonacci2 { public static void main(String arg[]) { ; ; ...
- JS中创建对象的方法及json
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...