线段树懒标记好题 HDU4578
(1)"1 x y c",代表 把区间 [x,y] 上的值全部加c
(2)"2 x y c",代表 把区间 [x,y] 上的值全部乘以c
(3)"3 x y c" 代表 把区间 [x,y]上的值全部赋值为c
(4)"4 x y p" 代表 求区间 [x,y] 上值的p次方和1<=p<=3
维护sum1[], sum2[], sum3[]分别为一次方、二次方、三次方的和
因为P只有1到3,(x+c)^2=(x^2)+(2*x*c+c^2),即我们可以从一次方和的结果推出二次方的和的结果。同理,我们也可以根据一次方的和的结果,二次方和的结果推出三次方和的结果。这样,我们可以用几个懒标记去记录这几个操作。但是这题明白上面这点还是不够的,因为,这几种更新操作之间会相互影响,比如对一个区间进行操作3之后,那么操作1和2就失效了。因此在PushDown传递懒标记的时候,传递的顺序也是重要的。
#include <bits/stdc++.h>
#include <string.h>
#include <iostream>
#include <stdio.h>
#define pb push_back
#define fi first
#define se second
#define lson(r) (r<<1)
#define rson(r) ((r<<1)|1) using namespace std; typedef long long ll; const int MAXN = 1e5+;
const int MAXV = ;
const int MAXE = ;
const ll MOD = ;
ll sum1[MAXN << ];
ll sum2[MAXN << ];
ll sum3[MAXN << ];
ll addmark[MAXN << ];
ll setmark[MAXN << ];
ll mulmark[MAXN << ]; void pushDown(int root, int l, int r)
{
int num = (r-l+);
ll numr = num >> ;
ll numl = num - numr;
//思考了半天用-1还是不够优秀呀 只需要把另外优先级低的懒标记 标记的左右子即可
//修改了半天 哎哎哎 这道题目深入理解懒标记
if (setmark[root])
{
ll setval = setmark[root];
//cout << "set" << l << " " << r << " " << setmark[root] << endl;
sum1[lson(root)] = (numl*setval) % MOD;
sum1[rson(root)] = (numr*setval) % MOD;
sum2[lson(root)] = (numl*setval*setval) % MOD;
sum2[rson(root)] = (numr*setval*setval) % MOD;
sum3[lson(root)] = (numl*setval*setval*setval) % MOD;
sum3[rson(root)] = (numr*setval*setval*setval) % MOD;
setmark[lson(root)] = setval;
setmark[rson(root)] = setval;
addmark[lson(root)] = addmark[rson(root)] = ;
mulmark[lson(root)] = mulmark[rson(root)] = ;
setmark[root] = ;
}
if (mulmark[root] != )
{
ll mulval = mulmark[root];
sum1[lson(root)] = (sum1[lson(root)]*mulval) % MOD;
sum1[rson(root)] = (sum1[rson(root)]*mulval) % MOD;
sum2[lson(root)] = (sum2[lson(root)]*mulval*mulval) % MOD;
sum2[rson(root)] = (sum2[rson(root)]*mulval*mulval) % MOD;
sum3[lson(root)] = (sum3[lson(root)]*mulval*mulval*mulval) % MOD;
sum3[rson(root)] = (sum3[rson(root)]*mulval*mulval*mulval) % MOD;
mulmark[lson(root)] = (mulmark[lson(root)]*mulval) % MOD;
mulmark[rson(root)] = (mulmark[rson(root)]*mulval) % MOD;
addmark[lson(root)] = (addmark[lson(root)]*mulval) % MOD;
addmark[rson(root)] = (addmark[rson(root)]*mulval) % MOD;
mulmark[root] = ;
}
if (addmark[root])
{
ll addval = addmark[root];
sum3[lson(root)] = ((sum3[lson(root)]+numl*addval*addval*addval)%MOD+(*sum2[lson(root)]*addval+*sum1[lson(root)]*addval*addval)%MOD)%MOD;
sum3[rson(root)] = ((sum3[rson(root)]+numr*addval*addval*addval)%MOD+(*sum2[rson(root)]*addval+*sum1[rson(root)]*addval*addval)%MOD)%MOD;
sum2[lson(root)] = (((sum2[lson(root)] + numl*addval*addval) % MOD) + (*sum1[lson(root)]*addval)) % MOD;
sum2[rson(root)] = (((sum2[rson(root)] + numr*addval*addval) % MOD) + (*sum1[rson(root)]*addval)) % MOD;
sum1[lson(root)] = (sum1[lson(root)] + numl * addval) % MOD;
sum1[rson(root)] = (sum1[rson(root)] + numr * addval) % MOD;
addmark[lson(root)] = (addmark[lson(root)] + addval) % MOD;
addmark[rson(root)] = (addmark[rson(root)] + addval) % MOD;
addmark[root] = ;
}
}
void update(int root, int l, int r, int ul, int ur, int mathod, ll val)
{
if (l > ur || r < ul) return ;
if (l >= ul && r <= ur)
{
ll num = r-l+;
if (mathod == )
{
//cout << l << " " << r << " " << val << endl;
setmark[root] = val%MOD;
addmark[root] = ;
mulmark[root] = ;
sum1[root] = (num*val) % MOD;
sum2[root] = (num*val*val) % MOD;
sum3[root] = (num*val*val*val) % MOD;
}
else if (mathod == )
{
mulmark[root] = (mulmark[root]*val)%MOD;
addmark[root] = (val*addmark[root])%MOD;
sum1[root] = (sum1[root]*val) % MOD;
sum2[root] = (sum2[root]*val*val) % MOD;
sum3[root] = (sum3[root]*val*val*val) % MOD;
}
else if (mathod == )
{ //cout << l << " " << r << " " << sum1[root] << endl;
addmark[root] = (addmark[root]+val)%MOD;
sum3[root] = ((sum3[root]+num*val*val*val)%MOD+(*sum2[root]*val+*sum1[root]*val*val)%MOD)%MOD;
sum2[root] = ((sum2[root] + num*val*val) % MOD + (*sum1[root]*val)) % MOD;
sum1[root] = (sum1[root] + num * val) % MOD;
//cout << l << " " << r << " " << sum1[root] << endl;
}
return ;
}
pushDown(root, l, r);
int mid = (l+r) >> ;
if (ul <= mid) update(lson(root), l, mid, ul, ur, mathod, val);
if (ur > mid) update(rson(root), mid+, r, ul, ur, mathod, val);
sum1[root] = (sum1[lson(root)] + sum1[rson(root)]) % MOD;
sum2[root] = (sum2[lson(root)] + sum2[rson(root)]) % MOD;
sum3[root] = (sum3[lson(root)] + sum3[rson(root)]) % MOD;
//cout << l << " " << r << " " << sum1[root] << endl;
} int cnt = ;
ll query(int root, int l, int r, int ql, int qr, int p)
{
// cout << l << " " << r << endl;
if (l > qr || r < ql) return ;
if (l >= ql && r <= qr)
{
if (p == ) return sum1[root];
else if (p == ) return sum2[root];
else if (p == ) return sum3[root];
}
pushDown(root, l, r);
int mid = (l+r) >> ;
ll res = ;
if (ql <= mid) res = (res + query(lson(root), l, mid, ql, qr, p)) % MOD;
if (qr >= mid+) res = (res + query(rson(root), mid+, r, ql, qr, p)) % MOD;
return res;
}
int n, m;
int main()
{
// freopen("in.txt", "r", stdin);
while (~scanf("%d%d", &n, &m))
{
for(int i = ; i < MAXN << ; i++) mulmark[i] = ;
if (!n && !m) break;
memset(addmark, , sizeof(addmark));
//memset(mulmark, 1, sizeof(mulmark));
memset(setmark, , sizeof(setmark));
memset(sum1, , sizeof(sum1));
memset(sum2, , sizeof(sum2));
memset(sum3, , sizeof(sum3));
for (int i = ; i < m; i++)
{
int op, l, r, c;
scanf("%d%d%d%d", &op, &l, &r, &c);
if (op == )
{
update(, , n, l, r, , c);
}
else if (op == )
{
update(, , n, l, r, , c);
}
else if (op == )
{
update(, , n, l, r, , c);
}
else
{
ll ans = query(, , n, l, r, c);
cout << ans << endl;
}
}
}
return ;
}
线段树懒标记好题 HDU4578的更多相关文章
- 「雅礼集训 2017 Day2」线段游戏(线段树懒标记“启发式下传”,李超树)
题面 题解 加入一条线段,可以把它转化为在[L,R]区间内加一条线 y=ax+b (如果原线段与y轴平行,就相当于在{x1}处加一条线 y=max(y1,y2)) 我们可以把它加到线段树上,线段树上每 ...
- HDU 4578 Transformation --线段树,好题
题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...
- GSS4 - Can you answer these queries IV(线段树懒操作)
GSS4 - Can you answer these queries IV(线段树懒操作) 标签: 线段树 题目链接 Description recursion有一个正整数序列a[n].现在recu ...
- Codeforces 258E - Little Elephant and Tree(根号暴力/线段树+标记永久化/主席树+标记永久化/普通线段树/可撤销线段树,hot tea)
Codeforces 题目传送门 & 洛谷题目传送门 yyq:"hot tea 不常有,做过了就不能再错过了" 似乎这是半年前某场 hb 模拟赛的 T2?当时 ycx.ym ...
- poj 3264:Balanced Lineup(线段树,经典题)
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 32820 Accepted: 15447 ...
- hdu 1754:I Hate It(线段树,入门题,RMQ问题)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- hdu 4578 线段树(标记处理)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others) ...
- hdu 3954 线段树 (标记)
Level up Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- BZOJ4785 [Zjoi2017]树状数组 【二维线段树 + 标记永久化】
题目链接 BZOJ4785 题解 肝了一个下午QAQ没写过二维线段树还是很难受 首先题目中的树状数组实际维护的是后缀和,这一点凭分析或经验或手模观察可以得出 在\(\mod 2\)意义下,我们实际求出 ...
随机推荐
- java基础—基础语法1
一.标识符
- Linux运维笔记--第一部
CentOS 学习总结 ...
- [已解决] odoo12 菜单不显示,安装后多出菜单
描述:odoo11中自定义模块写的,除了res.partner,res.users使用odoo自带的.其他的写了一个中国城市l10n_cn_city模型,一个账单模型(继承l10n_cn_city). ...
- 转 消息队列之 RabbitMQ
转 https://www.jianshu.com/p/79ca08116d57 消息队列之 RabbitMQ 预流 2017.05.06 16:03* 字数 4884 阅读 80990评论 18喜欢 ...
- 笔记--Day1--python基础1
一.目录 1.Python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum),目前已经是使用频度特别高的开发语言. 主要应用领域: 云计算:云计算最火的语言,典型应用有Op ...
- verilog 1995 VS 2001 part1模块声明的扩展
1.模块声明的扩展 (1)端口声明(input/output/inout)同数据类型声明(reg /wire)放在同一语句中. (2)ANSI C风格的端口声明可以用于module/task/func ...
- Linux 文本编辑常用快捷键
一.编辑模式 vim有三种编辑模式 1. i 进入文本编辑模式 2. esc 进入命令编辑模式 命令编辑状态下 dd删除整行 3. :进入底行模式 底行模式状态 输入q 退出 w保存 wq 保存并 ...
- Linux下的硬件驱动——USB设备(转载)
usb_bulk_msg函数 当对usb设备进行一次读或者写时,usb_bulk_msg 函数是非常有用的; 然而, 当你需要连续地对设备进行读/写时,建议你建立一个自己的urbs,同时将urbs 提 ...
- Vmware安装与使用
1)双击击VMware Workstation启动安装 2)接下来Ctrl+N快捷键(或者点选菜单Flie->New virtual machine)来创建一个新的虚拟机. 3)Custom(a ...
- 《Scrum实战》第3次课【富有成效的每日站会】作业汇总
1组 崔儒: http://kecyru.blog.163.com/blog/static/2741661732017626101944123/ 2017-07-26 孟帅: http://www.c ...