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

题意:传送门

 原题目描述在最下面。

 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. 使用canvas给图片添加水印, canvas转换base64,,canvas,图片,base64等转换成二进制文档流的方法,并将合成的图片上传到服务器,

    一,前端合成带水印的图片 一般来说,生成带水印的图片由后端生成,但不乏有时候需要前端来处理.当然,前端处理图片一般不建议,一方面js的处理图片的方法不全,二是有些老版本的浏览器对canvas的支持度不 ...

  2. SQL复制数据表及表结构

    select * into 目标表名 from 源表名 insert into 目标表名(fld1, fld2) select fld1, 5 from 源表名 以上两句都是将'源表'的数据插入到'目 ...

  3. Delphi 判断某个系统服务是否存在及相关状态

    记得use WinSvc; //------------------------------------- // 获取某个系统服务的当前状态 // // return status code if s ...

  4. codeforces 447E or 446C 线段树 + fib性质或二次剩余性质

    CF446C题意: 给你一个数列\(a_i\),有两种操作:区间求和:\(\sum_{i=l}^{r}(a[i]+=fib[i-l+1])\).\(fib\)是斐波那契数列. 思路 (一) codef ...

  5. HDU-4825 Xor Sum(字典树求异或最大值)

    题目链接:点此 我的github地址:点此 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整 ...

  6. 使用python发送163邮件 qq邮箱

    使用python发送163邮件 def send_email(title, content): import smtplib from email.mime.multipart import MIME ...

  7. RF中滚动条的操作方法小结

    滚动条分为俩种,一:主页面中的滚动条.二:页面中的子页面的滚动条. 每种滚动条有都分为上下滑动与左右滑动. 下面分别介绍: 一:主页面的滚动条上下滑动: execute javascript      ...

  8. mvc 前台传入后台

    转自:http://blog.csdn.net/huangyezi/article/details/45274553 一个很简单的分部视图,Model使用的是列表,再来看看调用该分部视图的action ...

  9. CSS margin属性

    例子: p{ margin:2cm 4cm 3cm 4cm; } 结果如下: margin-top是上外边距 margin-right是右外边距 margin-bottom是下外边距 margin-l ...

  10. flex上下、左右居中

    tip:1)flex是用于div布局用的,作用于一级子元素(父元素写样式,作用于子元素) 2)弹性盒模型 3)英文解释justify-content: 对齐内容(内容一般写在主轴上)align-ite ...