好久没写线段树了,这题作为一个回味..

第一种操作的话,就是一个延迟标记。

第二种操作可以暴力更新下去,但是有一个优化,如果某区间内所有值都是一样的,或者最大值和最小值相差1,那么到此结束,不要继续往下面更新了。

这样一来的话,pushDown的时候要注意一下,如果该区间内所有值都一样,或者最大值和最小值相差1,那么延迟标记不要往下扔了,直接把该区间的信息传下去。如果该区间内所有值不一样,将延迟标记扔下去。

总体难度不算大,仔细一些就能AC。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-;
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x) {
char c = getchar(); x = ;while(!isdigit(c)) c = getchar();
while(isdigit(c)) { x = x * + c - ''; c = getchar(); }
} const int maxn=+;
struct Seg { LL sum,f,MAX,MIN; }s[*maxn];
int T,n,m; void pushUp(int rt)
{
s[rt].sum=s[*rt].sum+s[*rt+].sum;
s[rt].MAX=max(s[*rt].MAX,s[*rt+].MAX);
s[rt].MIN=min(s[*rt].MIN,s[*rt+].MIN);
} void pushDown(int l,int r,int rt)
{
if(s[rt].MIN==s[rt].MAX)
{
s[*rt].MIN=s[*rt+].MIN=s[rt].MIN;
s[*rt].MAX=s[*rt+].MAX=s[rt].MAX; int fz=(l+r)/-l+;
s[*rt].sum=(LL)fz*s[rt].MIN;
s[*rt+].sum=s[rt].sum-s[*rt].sum;
s[rt].f=s[*rt].f=s[*rt+].f=;
return;
} if(s[rt].MIN==s[rt].MAX-)
{
int Tmin=min(s[*rt].MIN,s[*rt+].MIN),Tmax=max(s[*rt].MAX,s[*rt+].MAX); int len,x1,x2;
if(s[*rt].MIN==s[*rt].MAX)
{
if(s[*rt].MIN==Tmin) s[*rt].MIN=s[*rt].MAX=s[rt].MIN;
else s[*rt].MIN=s[*rt].MAX=s[rt].MAX;
s[*rt].sum=(LL)((l+r)/-l+)*s[*rt].MIN;
}
else
{
len=(l+r)/-l+;
x1=(s[*rt].sum-s[*rt].MAX*(LL)len)/(s[*rt].MIN-s[*rt].MAX); x2=len-x1;
s[*rt].MAX=s[rt].MAX; s[*rt].MIN=s[rt].MIN;
s[*rt].sum=(LL)x1*s[*rt].MIN+(LL)x2*s[*rt].MAX;
} if(s[*rt+].MIN==s[*rt+].MAX)
{
if(s[*rt+].MIN==Tmin) s[*rt+].MIN=s[*rt+].MAX=s[rt].MIN;
else s[*rt+].MIN=s[*rt+].MAX=s[rt].MAX;
s[*rt+].sum=(r-(l+r)/)*s[*rt+].MIN;
}
else
{
len=r-(l+r)/;
x1=(s[*rt+].sum-s[*rt+].MAX*(LL)len)/(s[*rt+].MIN-s[*rt+].MAX); x2=len-x1;
s[*rt+].MAX=s[rt].MAX; s[*rt+].MIN=s[rt].MIN;
s[*rt+].sum=(LL)x1*s[*rt+].MIN+(LL)x2*s[*rt+].MAX;
}
s[rt].f=s[*rt].f=s[*rt+].f=;
return;
} if(s[rt].f==) return; s[*rt].f=s[*rt].f+s[rt].f;
s[*rt+].f=s[*rt+].f+s[rt].f; s[*rt].MAX=s[*rt].MAX+s[rt].f;
s[*rt+].MAX=s[*rt+].MAX+s[rt].f; s[*rt].MIN=s[*rt].MIN+s[rt].f;
s[*rt+].MIN=s[*rt+].MIN+s[rt].f; int m=(l+r)/;
s[*rt].sum=s[*rt].sum+(LL)(m-l+)*s[rt].f;
s[*rt+].sum=s[*rt+].sum+(LL)(r-m)*s[rt].f; s[rt].f=;
} void build(int l,int r,int rt)
{
s[rt].f=; s[rt].MAX=; s[rt].MIN=; s[rt].sum=;
if(l==r)
{
read(s[rt].sum);
s[rt].f=; s[rt].MAX=s[rt].sum; s[rt].MIN=s[rt].sum;
return;
}
int m=(l+r)/;
build(l,m,*rt);
build(m+,r,*rt+);
pushUp(rt);
} void add(int L,int R,int x,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
s[rt].f=s[rt].f+x; s[rt].MAX=s[rt].MAX+x;
s[rt].MIN=s[rt].MIN+x; s[rt].sum=s[rt].sum+(r-l+)*(LL)x;
return;
}
pushDown(l,r,rt);
int m=(l+r)/;
if(L<=m) add(L,R,x,l,m,*rt);
if(R>m) add(L,R,x,m+,r,*rt+);
pushUp(rt);
} LL quary(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) return s[rt].sum;
pushDown(l,r,rt);
int m=(l+r)/; LL x1=,x2=;
if(L<=m) x1=quary(L,R,l,m,*rt);
if(R>m) x2=quary(L,R,m+,r,*rt+);
pushUp(rt);
return x1+x2;
} void force(int l,int r,int rt)
{
if(l==r)
{
s[rt].sum=(LL)sqrt(1.0*s[rt].sum);
s[rt].MIN=s[rt].MAX=s[rt].sum;
return;
}
if(s[rt].MIN==s[rt].MAX)
{
s[rt].MAX=s[rt].MIN=(LL)sqrt(1.0*s[rt].MIN);
s[rt].sum=(LL)(r-l+)*s[rt].MIN;
return;
} if(s[rt].MIN==s[rt].MAX-)
{
int len=r-l+;
int x1=(s[rt].sum-s[rt].MAX*(LL)len)/(s[rt].MIN-s[rt].MAX), x2=len-x1;
s[rt].MAX=(LL)sqrt(1.0*s[rt].MAX);
s[rt].MIN=(LL)sqrt(1.0*s[rt].MIN);
s[rt].sum=(LL)x1*s[rt].MIN+(LL)x2*s[rt].MAX; return;
} pushDown(l,r,rt);
int m=(l+r)/;
if(s[*rt].MAX!=) force(l,m,*rt);
if(s[*rt+].MAX!=) force(m+,r,*rt+);
pushUp(rt);
} void update(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) { if(s[rt].MAX==) return; force(l,r,rt); return; }
pushDown(l,r,rt);
int m=(l+r)/;
if(L<=m&&s[*rt].MAX!=) update(L,R,l,m,*rt);
if(R>m&&s[*rt+].MAX!=) update(L,R,m+,r,*rt+);
pushUp(rt);
} int main()
{
scanf("%d",&T); while(T--)
{
read(n); read(m); build(,n,);
for(int i=;i<=m;i++)
{
int op,L,R,x;
read(op); read(L); read(R);
if(op==) { read(x); add(L,R,x,,n,); }
else if(op==) update(L,R,,n,);
else if(op==) printf("%lld\n",quary(L,R,,n,));
}
}
return ;
}

HDU 5828 Rikka with Sequence的更多相关文章

  1. 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

    // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...

  2. HDU 5828 Rikka with Sequence (线段树)

    Rikka with Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...

  3. hdu 5828 Rikka with Sequence 线段树

    Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...

  4. HDU 5828 Rikka with Sequence(线段树 开根号)

    Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  5. HDU 5828 Rikka with Sequence (线段树+剪枝优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...

  6. HDU 5828 Rikka with Sequence(线段树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5828 [题目大意] 给出一个数列,要求支持区间加法,区间开方和区间和查询操作. [题解] 考虑开方 ...

  7. HDU 5828 Rikka with Sequence(线段树区间加开根求和)

    Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...

  8. hdu 5204 Rikka with sequence 智商不够系列

    Rikka with sequence Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...

  9. HDU - 6087 Rikka with Sequence (可持久化treap+倍增+重构)

    题目链接 感谢Dream_Lolita的题解,经过无数次失败的尝试之后终于AC了... 线段树是维护区间信息的强大工具,但它的形态是固定的,只支持修改和删除操作,不支持插入.反转.复制.分裂合并等操作 ...

随机推荐

  1. xml文件查找重复元素(超简单版)

    使用WPS,新建一个表格文件,将xml拖入表格,点数据,选中存在重复项的列,点高亮重复项,OK.

  2. vg

  3. coordinate transformation

    $X_{0}$为$I$在$O_{0}$系的坐标${\left(\begin{array}{c}x_0 \\y_0 \\z_0 \\\end{array}\right)}$,$X_{1}$为$I$在$O ...

  4. 分布式版本控制系统Git-----3.图形化Tortoisegit创建本地库并且提交到远程服务器上

    [前提你已经有了自己的远程仓库帐号密码和HTTP地址] PS:图形化会方便,但是个人认为还是敲命令比较好,会锻炼人的思维和逻辑. 1.首先在任意一个地方创建test目录.若要把test目录放在Git的 ...

  5. Xcode-之项目重命名

    一.前言 在iOS开发过程中,对于以前的项目或者想改一下项目的名字,都会遇到比较麻烦的事情.直接改项目名,然而它会牵扯一大堆问题,并且不能把所有的名字都能改过来.有些文件改了项目名后,引导路径错误,导 ...

  6. linux卸载rpm包

    先查找要卸载的rpm包:比如cpp: #rpm -qa | grep cpp #rpm -e cpp-2.333x.x 如果提示有依赖,执行: #rpm -e cpp-2222 --nodeps

  7. 老司机的奇怪noip模拟T1-guanyu

    1. 关羽(guanyu.cpp/c/pas )[问题描述]xpp 每天研究天文学研究哲学,对于人生又有一些我们完全无法理解的思考.在某天无聊学术之后, xpp 打开了 http://web.sang ...

  8. github上一些觉得对自己工作有用的项目收集

    usefullProjectCollect github上一些觉得对自己工作有用的项目收集 技能类 markdown语法中文说明 全文检索 elasticsearch bigdesk elastics ...

  9. Storm常见模式——批处理

    Storm对流数据进行实时处理时,一种常见场景是批量一起处理一定数量的tuple元组,而不是每接收一个tuple就立刻处理一个tuple,这样可能是性能的考虑,或者是具体业务的需要. 例如,批量查询或 ...

  10. Java Swing 日期控件(转载)

    http://www.cnblogs.com/lzy1991/p/5714935.html