参考:https://www.cnblogs.com/H-Vking/p/4297973.html

题意:

虽然是比较裸的线段树,但是比较麻烦,并且有很多细节需要考虑,对着别人的ac代码debug了一个晚上。纪念一下

 这道题坑在有三种询问:set , add , mul。所以lazy标记要有三个,如果三个标记同时出现的处理方法——当更新set操作时,就把add标记和mul标记全部取消;当更新mul操作时,如果当前节点add标记存在,就把add标记改为:add * mul。这样的话就可以在PushDown()操作中先执行set,然后mul,最后add。

  麻烦在有三种询问:和 , 平方和 , 立方和。对于set和mul操作来说,这三种询问都比较好弄。

  对于add操作,和的话就比较好弄,按照正常方法就可以;

  平方和这样来推:(a + c)2 = a2 + c2 + 2ac  , 即sum2[rt] = sum2[rt] + (r - l + 1) * c * c + 2 * sum1[rt] * c;

  立方和这样推:(a + c)3 = a3 + c3 + 3a(a2 + ac) , 即sum3[rt] = sum3[rt] + (r - l + 1) * c * c * c + 3 * c * (sum2[rt] + sum1[rt] * c);

  几个注意点:add标记取消的时候是置0,mul标记取消的时候是置1;在PushDown()中也也要注意取消标记,如set操作中取消add和mul,mul操作中更新add; 在add操作中要注意sum3 , sum2 , sum1的先后顺序,一定是先sum3 , 然后sum2 , 最后sum1; int容易爆,还是用LL要保险一点; 最后就是运算较多,不要漏掉东西。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include <iterator> using namespace std;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define debug(x) cerr << #x << " = " << x << "\n"; typedef long long ll;
const int maxn = 1e5+;
const int mdd = ; struct node {
int l,r;
ll sum1,sum2,sum3;
ll lazy1,lazy2,lazy3;
}st[maxn<<]; void allmdd(int rt)
{
st[rt].sum1 = st[rt].sum1%mdd;
st[rt].sum2 = st[rt].sum2%mdd;
st[rt].sum3 = st[rt].sum3%mdd;
} void pushup(int rt)
{
st[rt].sum1 = (st[rt<<].sum1 + st[rt<<|].sum1)%mdd;
st[rt].sum2 = (st[rt<<].sum2 + st[rt<<|].sum2)%mdd;
st[rt].sum3 = (st[rt<<].sum3 + st[rt<<|].sum3)%mdd;
} void pushdown(int rt)
{
int len = st[rt].r - st[rt].l + ;
int llen = len - (len>>);
int rlen = len>>;
if(st[rt].lazy3)
{
ll c = st[rt].lazy3%mdd;
st[rt<<].lazy3 = st[rt<<|].lazy3 = st[rt].lazy3;
st[rt<<].lazy1 = st[rt<<|].lazy1 = ;
st[rt<<].lazy2 = st[rt<<|].lazy2 = ; st[rt<<].sum1 = (llen * (c%mdd))%mdd;
st[rt<<|].sum1 = (rlen * c)%mdd; st[rt<<].sum2 = (llen * (c * c)%mdd ) %mdd;
st[rt<<|].sum2 = ((rlen * ((c * c)%mdd))%mdd)%mdd; st[rt<<].sum3 = (llen * ((c * c)%mdd * (c % mdd))%mdd)%mdd;
st[rt<<|].sum3 = (rlen * ((c * c)%mdd * (c % mdd))%mdd)%mdd;
st[rt].lazy3 = ;
} if(st[rt].lazy2 != )
{
ll c = st[rt].lazy2 % mdd;
st[rt<<].lazy2 = (st[rt<<].lazy2 * c) % mdd;
st[rt<<|].lazy2 = (st[rt<<|].lazy2 * c) % mdd;
if(st[rt<<].lazy1){
st[rt<<].lazy1 = (st[rt<<].lazy1 * c)%mdd;
}
if(st[rt<<|].lazy1){
st[rt<<|].lazy1 = (st[rt<<|].lazy1 * c)%mdd;
}
st[rt<<].sum1 = (st[rt<<].sum1 * c)%mdd;
st[rt<<|].sum1 = (st[rt<<|].sum1 * c)%mdd; st[rt<<].sum2 = ((st[rt<<].sum2 * c%mdd)*c)%mdd;
st[rt<<|].sum2 = ((st[rt<<|].sum2 * c%mdd)*c)%mdd; st[rt<<].sum3 = ((((st[rt<<].sum3 * c)%mdd)*c%mdd)*c)%mdd;
st[rt<<|].sum3 = ((((st[rt<<|].sum3 * c)%mdd)*c%mdd)*c)%mdd;
st[rt].lazy2 = ;
} if(st[rt].lazy1)
{
ll c = st[rt].lazy1;
st[rt<<].lazy1 = (st[rt<<].lazy1 + c)%mdd;
st[rt<<|].lazy1 = (st[rt<<|].lazy1 +c)%mdd;
//注意sum3,sum2,sum1 的顺序;
st[rt<<].sum3 = st[rt<<].sum3 + ((c%mdd)*c%mdd)*c%mdd*llen + *c*((st[rt<<].sum2 + st[rt<<].sum1 * c)%mdd);
st[rt<<|].sum3 = st[rt<<|].sum3 + ((c%mdd)*c%mdd)*c%mdd*rlen +*c*((st[rt<<|].sum2 + st[rt<<|].sum1 * c)%mdd); st[rt<<].sum2 = st[rt<<].sum2 + (((llen *c)%mdd) * c)%mdd + *(st[rt<<].sum1)%mdd*c;
st[rt<<|].sum2 = st[rt<<|].sum2 + (((rlen *c)%mdd) * c)%mdd + *(st[rt<<|].sum1*c)%mdd; st[rt<<].sum1 = st[rt<<].sum1 + (llen*c)%mdd;
st[rt<<|].sum1 = st[rt<<|].sum1 + (rlen*c)%mdd; allmdd(rt<<);allmdd(rt<<|);
st[rt].lazy1 = ;
}
} void build(int l,int r,int rt)
{
st[rt].sum1 = st[rt].sum2 = st[rt].sum3 = ;
st[rt].lazy1 = st[rt].lazy3 = ;
st[rt].lazy2 = ;
st[rt].l = l,st[rt].r = r;
int mid = (l + r) >> ;
if(l == r)return;
build(lson);
build(rson);
pushup(rt);
}
void update(int l,int r,int rt,int L,int R,int c,int op)
{
if(l >= L&&r <= R)
{
if(op==)
{
st[rt].lazy1 += c;
st[rt].sum3 = (st[rt].sum3 + ((c*c%mdd)*c)%mdd*(r-l+)%mdd + (*c*(st[rt].sum2 + st[rt].sum1*c)%mdd))%mdd;
st[rt].sum2 = (st[rt].sum2 + (c*c)%mdd*(r-l+)%mdd + ( * st[rt].sum1 * c)%mdd)%mdd;
st[rt].sum1 = (st[rt].sum1 + (r-l+)*c%mdd)%mdd;
}
else if(op==)
{
st[rt].lazy2 = (st[rt].lazy2 * c)%mdd;
if(st[rt].lazy1)
st[rt].lazy1 = (st[rt].lazy1 * c)%mdd;
st[rt].sum1 = (st[rt].sum1 * c %mdd)%mdd;
st[rt].sum2 = (st[rt].sum2 * ((c * c) %mdd))%mdd;
st[rt].sum3 = (st[rt].sum3 * (((c * c)%mdd * c) % mdd))%mdd;
}
else if(op==)
{
st[rt].lazy3 = c;
st[rt].lazy1 = ;
st[rt].lazy2 = ;
st[rt].sum1 = (((r-l+)*c )% mdd);
st[rt].sum2 = (((((r-l+)* c)%mdd )* c %mdd))%mdd;
st[rt].sum3 = ((r-l+)* (((c * c)%mdd * c) % mdd));
}
return;
} int mid = (l+r)>>;
pushdown(rt);
if(L<=mid)update(lson,L,R,c,op);
if(R>mid)update(rson,L,R,c,op);
pushup(rt);
}
ll query(int l,int r,int rt,int L,int R,int c)
{
if(l>=L&&r<=R)
{
if(c == )return st[rt].sum1%mdd;
else if(c == )return st[rt].sum2%mdd;
else return st[rt].sum3%mdd;
}
int mid = (l+r)>>;
ll ans = ;
pushdown(rt);
if(L<=mid)ans = (ans + query(lson,L,R,c))%mdd;
if(R>mid)ans = (ans + query(rson,L,R,c))%mdd;
return ans;
}
int main(){
// freopen("input","r",stdin);
int n,m;
while(scanf("%d%d", &n, &m)==&&n+m)
{
// debug(n);
build(,n,);
while(m--)
{
int op;
int a,b,c;
scanf("%d%d%d%d", & op, & a,& b, & c);
if(op==){
printf("%lld\n", query(,n,,a,b,c)%mdd);
}
else {
update(,n,,a,b,c,op);
}
}
}
return ;
}

HDU4578 线段树(区间更新 + 多种操作)和平方,立方的更多相关文章

  1. HDU4578 线段树(区间更新 + 多种操作)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578  , 线段树的区间更新 + 多种操作,好题. 虽然是比较裸的线段树,但是比较麻烦,并且有很多细节 ...

  2. hdu4578线段树区间更新

    /* 只有在区间中的数字不相同时才pushdown:往子区间传递数字再到子区间更新,同时该区间的flag置0 更新完左右子区间后进行pushup,如果左右子区间数字相同,那么把子区间合并,子区间数字置 ...

  3. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们 ...

  4. HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...

  5. HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...

  6. HDU5039--Hilarity DFS序+线段树区间更新 14年北京网络赛

    题意:n个点的树,每个条边权值为0或者1, q次操作 Q 路径边权抑或和为1的点对数, (u, v)(v, u)算2个. M i修改第i条边的权值 如果是0则变成1, 否则变成0 作法: 我们可以求出 ...

  7. hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

    #1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题 ...

  8. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  9. POJ 3468:A Simple Problem with Integers(线段树区间更新模板)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 141093 ...

随机推荐

  1. jdk1.8HashMap底层数据结构:散列表+链表+红黑树,jdk1.8HashMap数据结构图解+源码说明

    一.前言 本文由jdk1.8源码整理而得,附自制jdk1.8底层数据结构图,并截取部分源码加以说明结构关系. 二.jdk1.8 HashMap底层数据结构图 三.源码 1.散列表(Hash table ...

  2. 【Android】error: Error retrieving parent for item: No resource found that matches the given name 'Theme.Sherlock.Light.NoActionBar'.

    问题: res 文件夹下的 values 下的 styles.xml <style name="Sherlock.Light.NoActionBar" parent=&quo ...

  3. iOS 注释

    1) 参数的注释: UIButton *btnSend;/**< 发送按钮 */ 效果: 2) 方法的注释: type1(无参数): /** table 相关设置 */ -(void)confi ...

  4. .NET Core on K8S学习实践系列文章索引(Draft版)

    一.关于这个系列 自从去年(2018年)底离开工作了3年的M公司加入X公司之后,开始了ASP.NET Core的实践,包括微服务架构与容器化等等.我们的实践是渐进的,当我们的微服务数量到了一定值时,发 ...

  5. 【转载】【VSCode】Windows下VSCode编译调试c/c++

    转载自:http://blog.csdn.net/c_duoduo/article/details/51615381 懒得自己配置或自己配置出现不明问题的朋友可以点这里: [VSCode]Window ...

  6. Oracle DBLink跨数据库访问SQL server数据同步 踩坑实录

    项目需求:这里暂且叫A公司吧,A公司有一套人事管理软件,需要与我们公司的软件做人员信息同步,A公司用的是SQL server数据库,我们公司用的Oracle,接口都不会开发(一万句"fuck ...

  7. 微服务SpringCloud之Spring Cloud Config配置中心SVN

    在回来的路上看到一个个的都抱着花,吃了一路的狗粮,原本想着去旁边的工业园里跑跑步呢,想想还是算了,人家过七夕,俺们过巴西.上一博客学习了Spring Cloud Config使用git作为配置中心,本 ...

  8. 【Java例题】8.2 手工编写字符串统计的可视化程序

      2. 手工编写字符串统计的可视化程序. 一个Frame窗体容器,布局为null,两个TextField组件,一个Button组件. Button组件上添加ActionEvent事件监听器Actio ...

  9. Java ActionListenner类的一些理解

    Java的ActionListenner事实上我去年年这个时候大概就已经接触到了,也学会了比较简单的使用.但却始终不能理解ActionListenner的一系列的运行是怎么维持这么一个联系的? 我产生 ...

  10. unity 四叉树管理场景

    当场景元素过多时,需要实时的显示及隐藏物体使得性能提示,但是物体那么多,怎么知道哪些物体需要显示,哪些物体不需要显示的.当然,遍历物体判断该物体是否可以显示是最容易想到的方法,但是每次更新要遍历所有物 ...