HDU4578-代码一点都不长的线段树
(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
题意:传送门
原题目描述在最下面。
4种操作,1:区间加法,2:区间乘法,3:区间的所有数都变成一个数,4:访问区间每个数的p次方和(1 <= p <= 3)。
思路:
三个lazy标记:lazy1表示区间加上的数的延迟,lazy2表示区间乘上的数的延迟,lazy3表示区间变成的那个数字。初始化lazy1 = lazy3 = 0, lazy2 = 1
.
如果进行3号操作,则将lazy1和lazy2全部恢复初始值。
对于1,2号操作,假设原数是x,乘上a,加上b。则 \(a \Rightarrow a \times x + b\) 。
$$sum1 = \sum x \Rightarrow \sum (a\times x + b) = sum1 \times a + b \times length$$
$$sum2 = \sum x^2 \Rightarrow \sum (a\times x + b)^2 \Rightarrow \sum (a^2\times x2+b2+2\times a\times b\times x)=sum2\times a2+b2 \times length+2\times a\times b\times sum1
\]
注意了,再进行更新sum操作时,要先更新sum3再更新sum2最后更新sum1。比如sum3式子中的sum2的含义是原始数列的sum2,不是更新后的sum2。
然后就是对于push_down中的lazy1和lazy2的处理。
\(lazy1 \Rightarrow lazy1\times a + b\)
$lazy2 \Rightarrow lazy2\times a $
(因为update哪里忘了写return;
,导致debug一天)
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
#include<assert.h>
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x)&(-(x))
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = (int)1e5+7;
const int mod = 10007;
int n, q;
int ar[N];
struct lp{
int l,r;
LL sum1,sum2,sum3,d;
LL lazy1,lazy2,lazy3;
}cw[N<<2];
//pushdown先乘除后加减
//加法 lazy1 lazy2 乘法
void push_up(int rt){
cw[rt].sum1 = (cw[lson].sum1+cw[rson].sum1)%mod;
cw[rt].sum2 = (cw[lson].sum2+cw[rson].sum2)%mod;
cw[rt].sum3 = (cw[lson].sum3+cw[rson].sum3)%mod;
}
void build(int l,int r,int rt){
int m=(l+r)>>1;
cw[rt].l=l;cw[rt].r=r;
cw[rt].d=r-l+1;
cw[rt].sum1 = cw[rt].sum2 = cw[rt].sum3=0;
cw[rt].lazy1 = cw[rt].lazy3 = 0;
cw[rt].lazy2 = 1;
if(l==r){return;}
build(l,m,lson); build(m+1,r,rson);
push_up(rt);
}
//pushdown先乘除后加减
void push_down(int rt){
if(cw[rt].lazy3){
LL tmp = cw[rt].lazy3*cw[rt].lazy3%mod*cw[rt].lazy3%mod;
cw[lson].lazy1=cw[rson].lazy1=0;
cw[lson].lazy2=cw[rson].lazy2=1;
cw[lson].lazy3=cw[rson].lazy3=cw[rt].lazy3;
cw[lson].sum3 = cw[lson].d*tmp%mod;
cw[rson].sum3 = cw[rson].d*tmp%mod;
cw[lson].sum2 = cw[lson].d*cw[rt].lazy3%mod*cw[rt].lazy3%mod;
cw[rson].sum2 = cw[rson].d*cw[rt].lazy3%mod*cw[rt].lazy3%mod;
cw[lson].sum1 = cw[lson].d*cw[rt].lazy3%mod;
cw[rson].sum1 = cw[rson].d*cw[rt].lazy3%mod;
cw[rt].lazy3 = 0;
}
if(cw[rt].lazy1!=0||cw[rt].lazy2!=1){
LL add = cw[rt].lazy1, mul = cw[rt].lazy2;
LL l1=cw[lson].sum1,l2=cw[lson].sum2,l3=cw[lson].sum3;
LL r1=cw[rson].sum1,r2=cw[rson].sum2,r3=cw[rson].sum3;
LL tmp = mul*mul%mod*mul%mod;
cw[lson].lazy1=(cw[lson].lazy1*mul%mod+add)%mod;
cw[rson].lazy1=(cw[rson].lazy1*mul%mod+add)%mod;
cw[lson].lazy2=cw[lson].lazy2*mul%mod;
cw[rson].lazy2=cw[rson].lazy2*mul%mod;
cw[lson].sum3=(cw[lson].sum3*tmp%mod + add*add%mod*add%mod*cw[lson].d%mod + 3*cw[lson].sum2*mul%mod*mul%mod*add%mod + 3*cw[lson].sum1*mul%mod*add%mod*add%mod)%mod;
cw[rson].sum3=(cw[rson].sum3*tmp%mod + add*add%mod*add%mod*cw[rson].d%mod + 3*cw[rson].sum2*mul%mod*mul%mod*add%mod + 3*cw[rson].sum1*mul%mod*add%mod*add%mod)%mod;
cw[lson].sum2=(cw[lson].sum2*mul%mod*mul%mod + add*add%mod*cw[lson].d%mod + 2*mul*add*cw[lson].sum1)%mod;
cw[rson].sum2=(cw[rson].sum2*mul%mod*mul%mod + add*add%mod*cw[rson].d%mod + 2*mul*add*cw[rson].sum1)%mod;
cw[lson].sum1=(cw[lson].sum1*mul+add*cw[lson].d)%mod;
cw[rson].sum1=(cw[rson].sum1*mul+add*cw[rson].d)%mod;
cw[rt].lazy1 = 0;cw[rt].lazy2 = 1;
}
}
//op==1 加法, op==2 乘法, op==3 改变值
void update(int L,int R,int op,int z,int rt){
int l=cw[rt].l, r=cw[rt].r, mid=(l+r)>>1;
if(cw[rt].l>R||cw[rt].r<L)return;
if(L<=l&&r<=R){
LL l1 = cw[rt].sum1, l2 = cw[rt].sum2;
if(op==1){//加法
cw[rt].lazy1 = (z + cw[rt].lazy1)%mod;
cw[rt].sum3 = (cw[rt].sum3 + (z*z%mod)*z%mod*cw[rt].d%mod + 3*z*(cw[rt].sum2+(cw[rt].sum1*z)%mod)%mod)%mod;
cw[rt].sum2 = (cw[rt].sum2 + cw[rt].d*z%mod*z%mod + 2*z*cw[rt].sum1%mod)%mod;
cw[rt].sum1 = (cw[rt].sum1 + cw[rt].d*z%mod)%mod;
}else if(op==2){//乘法
cw[rt].lazy1 = cw[rt].lazy1*z%mod;
cw[rt].lazy2 = cw[rt].lazy2*z%mod;
cw[rt].sum1 = cw[rt].sum1*z%mod;
cw[rt].sum2 = (cw[rt].sum2*z%mod)*z%mod;
cw[rt].sum3 = ((cw[rt].sum3*z%mod)*z%mod)*z%mod;
}else{
cw[rt].lazy1=0;cw[rt].lazy2=1;
cw[rt].lazy3=z;
cw[rt].sum3 = cw[rt].d*z%mod*z%mod*z%mod;
cw[rt].sum2 = cw[rt].d*z%mod*z%mod;
cw[rt].sum1 = cw[rt].d*z%mod;
}
return;
}
if(cw[rt].l==cw[rt].r)return;
push_down(rt);
if(L>mid)update(L,R,op,z,rson);
else if(R<=mid)update(L,R,op,z,lson);
else{
update(L,mid,op,z,lson);
update(mid+1,R,op,z,rson);
}
push_up(rt);
}
LL query(int L,int R,int op,int rt){
int l=cw[rt].l, r=cw[rt].r, mid=(l+r)>>1;
if(L<=l&&r<=R){
if(op==1)return cw[rt].sum1;
else if(op==2)return cw[rt].sum2;
return cw[rt].sum3;
}
if(cw[rt].l==cw[rt].r)return 0;
push_down(rt);
LL sum = 0;
if(L>mid) sum = query(L,R,op,rson);
else if(R<=mid) sum = query(L,R,op,lson);
else {
sum = query(L,mid,op,lson);
sum += query(mid+1,R,op,rson);
}
return (sum%mod);
}
int main(){
while(~scanf("%d%d", &n,&q)&&(n+q)){
build(1,n,1);
while(q--){
int op,l,r,z;
scanf("%d%d%d%d",&op,&l,&r,&z);
if(op<=3){
z%=mod;
update(l,r,op,z,1);
}else{
printf("%lld\n", query(l,r,z,1));
}
}
}
return 0;
}
####原题目描述:
Problem Description
Yuanfang is puzzled with the question below:
There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation akInput
There are no more than 10 test cases.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
Output
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
Sample Input
5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
Sample Output
307
7489
Source
2013ACM-ICPC杭州赛区全国邀请赛
HDU4578-代码一点都不长的线段树的更多相关文章
- HDU 4417.Super Mario-可持久化线段树(无修改区间小于等于H的数的个数)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 线段树详解 (原理,实现与应用)(转载自:http://blog.csdn.net/zearot/article/details/48299459)
原文地址:http://blog.csdn.net/zearot/article/details/48299459(如有侵权,请联系博主,立即删除.) 线段树详解 By 岩之痕 目录: 一:综述 ...
- Mango DS Training #48 ---线段树2 解题手记
Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38966#overview A.Count Color ...
- 线段树 Interval Tree
一.线段树 线段树既是线段也是树,并且是一棵二叉树,每个结点是一条线段,每条线段的左右儿子线段分别是该线段的左半和右半区间,递归定义之后就是一棵线段树. 例题:给定N条线段,{[2, 5], [4, ...
- HDU 1166 敌兵布阵(线段树 单点更新)
点我看题目 题意 :HDU的中文题也不常见....这道题我就不详述了..... 思路 :这个题用线段树用树状数组都可以,用线段树的时候要注意输入那个地方,输入一个字符串的时候不要紧接着输入两个数字 ...
- bzoj 1513 [POI2006]Tet-Tetris 3D(二维线段树)
1513: [POI2006]Tet-Tetris 3D Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 540 Solved: 175[Submit ...
- [SinGuLaRiTy] ZKW线段树
[SinGuLaRiTy-1007] Copyrights (c) SinGuLaRiTy 2017. All Rights Reserved. 关于ZKW线段树 Zkw线段树是清华大学张昆玮发明非递 ...
- [poj3468]A Simple Problem with Integers_线段树
A Simple Problem with Integers 题目大意:给出n个数,区间加.查询区间和. 注释:1<=n,q<=100,000.(q为操作次数). 想法:嗯...学了这么长 ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
随机推荐
- C/C++ volatile
{ volatile和const关键很相似,都是修饰变量的,只是二者功能不一样. volatile在多线程当中经常使用,因为在某一线程多次调用某一个变量,编译器会进行优化,将该变量存放在在寄存器当中, ...
- openFrameworks Download
{ https://openframeworks.cc/zh_cn//download/ } 0.10.1 是最新发布的版本. 这个版本是修改了一些BUG的小版本,与版本 0.10.1100%兼容而且 ...
- Delphi ADOQuery的 DisableControls 和 EnableControls方法
DisableControls方法是在程序修改或后台有刷新记录的时候切断数据组件,如TTABLE.ADOQUERY等等与组件数据源的联系.如果没有切断,数据源中只要一有数据的改动,尤其是批量改动的话, ...
- iscroll refresh无效解决办法
最近用iscroll.js 写移动页面,效果还是挺好的.但,还是会遇到重新初始化的问题. var myScroll = new IScroll('#rule_wrapper',{ click:true ...
- A*启发式搜索基础
A*启发式搜索基础 传统的搜索方式是盲目搜索,即到每一步的时候并没有对每种情况进行有效的区分,这样的结果是浪费了大量的时间,对很多没有必要的数据进行了搜索. 而A*算法则在搜索的过程中会选取认为“最优 ...
- [CQOI2011]放棋子 题解(dp+组合数学)
Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数. 第二行包含c个正整数,即每个颜色的棋子数. 所有颜色的棋子总数保证不超过nm. N,M<=3 ...
- 用java进行测试php写的接口
<?php /* * @Author: anchen * @Date: 2018-07-06 13:53:19 * @Last Modified by: anchen * @Last Modif ...
- Centos7下Firewalld防火墙配置命令
前 言 服务端口日常被拦截,记录一下常用的命令便于查询 Firewalld服务管理 查看防火墙状态 1 systemctl status firewalld 开机启用/禁用防火墙 1 s ...
- node+webpack+vue的环境搭建
一般第一次搭建环境的时候,多多少少还是会出点状况的.这个时候多去百度,看牛人怎么解决,然后跟着尝试,多试几遍还是能解决的. 先说一下我安装的过程吧 1.我一开始按照官网的来搭建,失败了.报错内容是 ...
- 2-vim-打开和新建文件-01-打开/新建文件/打开定位到文件指定行
1.新建或打开文件 命令: vim 文件名 在终端中输入vi在后面跟上文件名即可. 如果文件已经存在,会直接打开文件. 如果文件不存在,会新建一个文件. 2.打开文件并定位到文件指定行. 命令: vi ...