(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

题意:传送门

 原题目描述在最下面。

 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

\[&emsp;$$sum3 = \sum x^3 \Rightarrow \sum (a\times x + b)^3 \Rightarrow \sum (a^3\times x^3 + b^3 + 3\times a^2\times x^2\times b+3\times a \times x\times b^2)= sum3 \times a^3 + b^3 \times length + 3\times sum2\times a^2 \times b+ 3\times sum1\times a\times b^2
\]

 注意了,再进行更新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-代码一点都不长的线段树的更多相关文章

  1. HDU 4417.Super Mario-可持久化线段树(无修改区间小于等于H的数的个数)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  2. 线段树详解 (原理,实现与应用)(转载自:http://blog.csdn.net/zearot/article/details/48299459)

    原文地址:http://blog.csdn.net/zearot/article/details/48299459(如有侵权,请联系博主,立即删除.) 线段树详解    By 岩之痕 目录: 一:综述 ...

  3. Mango DS Training #48 ---线段树2 解题手记

    Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38966#overview A.Count Color ...

  4. 线段树 Interval Tree

    一.线段树 线段树既是线段也是树,并且是一棵二叉树,每个结点是一条线段,每条线段的左右儿子线段分别是该线段的左半和右半区间,递归定义之后就是一棵线段树. 例题:给定N条线段,{[2, 5], [4, ...

  5. HDU 1166 敌兵布阵(线段树 单点更新)

     点我看题目  题意 :HDU的中文题也不常见....这道题我就不详述了..... 思路 :这个题用线段树用树状数组都可以,用线段树的时候要注意输入那个地方,输入一个字符串的时候不要紧接着输入两个数字 ...

  6. bzoj 1513 [POI2006]Tet-Tetris 3D(二维线段树)

    1513: [POI2006]Tet-Tetris 3D Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 540  Solved: 175[Submit ...

  7. [SinGuLaRiTy] ZKW线段树

    [SinGuLaRiTy-1007] Copyrights (c) SinGuLaRiTy 2017. All Rights Reserved. 关于ZKW线段树 Zkw线段树是清华大学张昆玮发明非递 ...

  8. [poj3468]A Simple Problem with Integers_线段树

    A Simple Problem with Integers 题目大意:给出n个数,区间加.查询区间和. 注释:1<=n,q<=100,000.(q为操作次数). 想法:嗯...学了这么长 ...

  9. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

随机推荐

  1. Hive学内置条件和字符串函数

    https://blog.csdn.net/skywalker_only/article/details/38752003 条件函数 下表为Hive支持的一些条件函数. 返回类型 函数名 描述 T i ...

  2. (一)CGI (通用网关接口) 简介

    CGI (通用网关接口)公共网关接口(Common Gateway Interface,CGI)是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能.CGI 应用程序能与浏览器 ...

  3. Office应用程序对照表

    任何Office应用程序(包括excel)的类型库都作为Office安装的一部分安装.类型库是特定于版本的(即,安装了哪个版本的Office). 例如,Office 2007版本为12.0,Offic ...

  4. 管理员技术(二): 访问练习用虚拟机、 命令行基础技巧 、 挂载并访问光盘设备、ls列表及文档创建、复制删除移动

    一.访问练习用虚拟机 目标: 学会在教学环境中访问练习用虚拟机,主要完成以下事项: 1> 快速重置教学虚拟机环境       2> 通过“虚拟系统管理器”访问虚拟机       3> ...

  5. Python 中练习题涉及到的无穷大和无穷小问题。

    首先来看一下所见的python联系题. inf = infinite 无限制的 float("inf")-1执行后的结果是:() A 1 B inf C -inf D 0 该考点考 ...

  6. svn启动服务

    bin目录添加到环境变量classpathsvn --version 查看版本svnadmin create D:\\xx 创建本地中央仓库启动svn服务 cmd命令 svnserve -d -r D ...

  7. 洛谷 P4173 残缺的字符串 (FFT)

    题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...

  8. vant实现三级联动

    首先要在vant 框架里边   复制一下   省市区的 地址数据在这里下载eare.js 格式 : var address = { province_list: { 110000: '北京市', }, ...

  9. 剑指offer——570~n-1中缺失的数字

    题目:0~n-1中缺失的数字. 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内. 在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字. ...

  10. js实现禁止页面拖拽图片

    document.ondragstart = function() {        return false;};