线段树懒标记好题 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\)意义下,我们实际求出 ...
随机推荐
- UI Testing in Xcode 7
参考文章: UI Testing in Xcode - WWDC 2015https://developer.apple.com/videos/play/wwdc2015-406/ Document ...
- VMWare安装苹果Mac OS X
随着iPhone.iPad.Mac等苹果产品越来越火爆,越来越多的初学者想要了解和尝试苹果平台,包括苹果操作系统Mac OS X.苹果演示软件Keynote.苹果开发工具Xcode等.然而,苹果电脑价 ...
- python生成四位随机数
有些时候需要发送短信给用户生成四位随机数字,这里在python中我们可以根据python自带的标准库random和string来实现. random下有三个可以随机取数的函数,分别是choice,ch ...
- python-matplotlib-lec1
接演前文. 设置属性的方法: 使用对象的set_*方法,单独设置每个属性:或使用plt.setp同时设置多个属性 # -*- coding: utf-8 -*- import numpy as np ...
- SQL登录注册练习
/class User package com.neusoft.bean; public class User { private int password; private String name; ...
- ARM系统调用
参考:Linux异常处理体系结构 linux系统调用表(system call table) Arm Linux系统调用流程详细解析-SWI ARM系统调用是通过SWI异常处理函数实现的,这里简要概 ...
- Servlet注意事项
注意事项 1.对于Servlet的应用程序的目录结构来说,若想让有些文件Servlet可以访问,而用户不能访问的时候,可以将其放置在WEB-INF目录下 2.ServletResponse中getwr ...
- 笔记-python-centos环境下安装配置
笔记-python-centos环境下安装配置 1. 准备工作 环境准备 centos6.5 mini,已有python 2.6.6 下载源码包 Python官网下载Gzipped sour ...
- InnoDB Redo Flush及脏页刷新机制深入分析
概要: 我们知道InnoDB采用Write Ahead Log策略来防止宕机数据丢失,即事务提交时,先写重做日志,再修改内存数据页,这样就产生了脏页.既然有重做日志保证数据持久性,查询时也可以直接从缓 ...
- java处理excel
JAVA EXCEL API:是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Windows操作系统也可以通过 ...