HDU - 4578Transformation——线段树+区间加法修改+区间乘法修改+区间置数+区间和查询+区间平方和查询+区间立方和查询

【题目描述】
HDU - 4578Transformation
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 ak<—ak+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<—ak×c, k = x,x+1,…,y.
Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<—c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.

Input
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
【题目分析】
这道题真的是老妖怪级别的了,此处省略吐槽两千字
题目的意思很明确,就是给你一个全为0 的数组,让你实现区间加法修改+区间乘法修改+区间置数+区间和查询+区间平方和查询+区间立方和查询功能。
根据需求,每个区间有三个需要维护的数据——区间和,区间平方和,区间立方和,有三种修改操作,因此需要三种标记,分别用来标记区间加法、区间乘法、区间置数
难点在于对于三种数据的快速维护和标记之间的关系

  1. 标记之间的关系(关键)
    我们为了实现区间修改就需要引入lazy标记(没有掌握这个的同学请出门左拐,详见线段树入门) ,但是当存在多种标记的时候处理标记的顺序就很重要,因为这反应了修改操作的效用关系以及时间关系。
    上面三种操作里面最厉害的显然是区间置数,一个区间置数后之前什么加法乘法统统作废。然后是区间乘法,因为区间乘法,因为对同一个区间,后来的乘法标记会对之前的加法标记产生影响,但是后来的加法标记对乘法标记却没有什么影响(先算乘法再算加法嘛)
    因此在处理区间置数的时候可以直接对区间加法置零,对区间乘法的标记置一
    在处理区间乘法的时候如果发现下面的区间还要进行区间加法就要修改区间加法的标记(给标记也乘上同一个数)
    在处理区间加法的时候对其他标记没有影响
    同样的,在下传标记的时候同样要面对这样的问题
    这样,后面的操作对前面操作的影响就能传递下去
  2. 三种数据的快速维护
    区间置数后三种数据直接计算
    区间乘法后立方和乘上乘数的立方,平方和乘上乘数的平方,区间和乘上乘数,需要注意取模(时刻取模,时刻提防爆数据)
    最麻烦的是区间加法
    对于区间和,应该加上区间长度乘上加数
    对于平方和,见下图
    在这里插入图片描述
    立方和同理
    【AC代码】(可写死我了)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<climits>
#include<queue>
#include<vector>using namespace std;
typedef long long ll;const int MAXN=100005;
const ll MOD=10007;struct node
{ll a,aa,aaa;
}tree[MAXN<<2];
ll set[MAXN<<2],add[MAXN<<2],multiply[MAXN<<2];
int n,m;
ll t;void pushdown(int k,int l,int r)
{int mid=(l+r)>>1; if(set[k]>0){tree[k<<1].a=set[k]%MOD*(mid-l+1)%MOD; tree[k<<1|1].a=set[k]%MOD*(r-mid)%MOD;tree[k<<1].aa=set[k]%MOD*set[k]%MOD*(mid-l+1)%MOD; tree[k<<1|1].aa=set[k]%MOD*set[k]%MOD*(r-mid)%MOD;tree[k<<1].aaa=set[k]%MOD*set[k]%MOD*set[k]%MOD*(mid-l+1)%MOD; tree[k<<1|1].aaa=set[k]%MOD*set[k]%MOD*set[k]%MOD*(r-mid)%MOD;set[k<<1]=set[k<<1|1]=set[k];	add[k<<1]=add[k<<1|1]=0;	//直接取消标记multiply[k<<1]=multiply[k<<1|1]=1;	//直接取消标记set[k]=0;}if(multiply[k]!=1){tree[k<<1].a=tree[k<<1].a*multiply[k]%MOD;tree[k<<1|1].a=tree[k<<1|1].a*multiply[k]%MOD;tree[k<<1].aa=tree[k<<1].aa*multiply[k]%MOD*multiply[k]%MOD;tree[k<<1|1].aa=tree[k<<1|1].aa*multiply[k]%MOD*multiply[k]%MOD;tree[k<<1].aaa=tree[k<<1].aaa*multiply[k]%MOD*multiply[k]%MOD*multiply[k]%MOD;tree[k<<1|1].aaa=tree[k<<1|1].aaa*multiply[k]%MOD*multiply[k]%MOD*multiply[k]%MOD;multiply[k<<1]=multiply[k<<1]*multiply[k]%MOD;multiply[k<<1|1]=multiply[k<<1|1]*multiply[k]%MOD;if(add[k<<1]) add[k<<1]=add[k<<1]*multiply[k]%MOD;	//注意对加法标记的影响if(add[k<<1|1]) add[k<<1|1]=add[k<<1|1]*multiply[k]%MOD;-multiply[k]=1;}if(add[k]>0){tree[k<<1].aaa=(((tree[k<<1].aaa+3*add[k]%MOD*tree[k<<1].aa%MOD)%MOD+3*add[k]%MOD*add[k]%MOD*tree[k<<1].a%MOD)%MOD+(mid-l+1)*add[k]%MOD*add[k]%MOD*add[k]%MOD)%MOD; //顺序很重要,应该先立方后平方再区间和(因为会用到原始数据)tree[k<<1|1].aaa=(((tree[k<<1|1].aaa+3*add[k]%MOD*tree[k<<1|1].aa%MOD)%MOD+3*add[k]%MOD*add[k]%MOD*tree[k<<1|1].a%MOD)%MOD+(r-mid)*add[k]%MOD*add[k]%MOD*add[k]%MOD)%MOD; tree[k<<1].aa=((tree[k<<1].aa+add[k]*add[k]%MOD*(mid-l+1)%MOD)%MOD+2*add[k]%MOD*tree[k<<1].a%MOD)%MOD;tree[k<<1|1].aa=((tree[k<<1|1].aa+add[k]*add[k]%MOD*(r-mid)%MOD)%MOD+2*add[k]%MOD*tree[k<<1|1].a%MOD)%MOD;tree[k<<1].a=(tree[k<<1].a+add[k]*(mid-l+1)%MOD)%MOD;tree[k<<1|1].a=(tree[k<<1|1].a+add[k]*(r-mid)%MOD)%MOD;add[k<<1]=(add[k<<1]+add[k])%MOD;add[k<<1|1]=(add[k<<1|1]+add[k])%MOD;//时刻注意取模add[k]=0;}
}void update(int k)
{tree[k].a=(tree[k<<1].a+tree[k<<1|1].a)%MOD;tree[k].aa=(tree[k<<1].aa+tree[k<<1|1].aa)%MOD;tree[k].aaa=(tree[k<<1].aaa+tree[k<<1|1].aaa)%MOD;
}void interval_add(int k,int l,int r,int x,int y,ll z)
{if(l>=x && r<=y){tree[k].aaa=(((tree[k].aaa+3*z%MOD*tree[k].aa%MOD)%MOD+3*z%MOD*z%MOD*tree[k].a)%MOD+(r-l+1)*z%MOD*z%MOD*z%MOD)%MOD;tree[k].aa=((tree[k].aa+2*z%MOD*tree[k].a%MOD)%MOD+(r-l+1)*z%MOD*z%MOD)%MOD;tree[k].a=(tree[k].a+z*(r-l+1)%MOD)%MOD;add[k]=(add[k]+z)%MOD;return;}int mid=(l+r)>>1;pushdown(k,l,r);if(x<=mid) interval_add(k<<1,l,mid,x,y,z);if(y>mid) interval_add(k<<1|1,mid+1,r,x,y,z);update(k); 
}void interval_multiply(int k,int l,int r,int x,int y,ll z)
{if(l>=x && r<=y){multiply[k]=(multiply[k]*z)%MOD;if(add[k]>0){add[k]=(add[k]*z)%MOD;}tree[k].a=tree[k].a*z%MOD;tree[k].aa=tree[k].aa*z%MOD*z%MOD;tree[k].aaa=tree[k].aaa*z%MOD*z%MOD*z%MOD;return;}int mid=(l+r)>>1;pushdown(k,l,r);if(x<=mid) interval_multiply(k<<1,l,mid,x,y,z);if(y>mid) interval_multiply(k<<1|1,mid+1,r,x,y,z);update(k); 
}void interval_set(int k,int l,int r,int x,int y,ll z)
{if(l>=x && r<=y){tree[k].a=z*(r-l+1)%MOD;tree[k].aa=z*z%MOD*(r-l+1)%MOD;tree[k].aaa=z*z%MOD*z%MOD*(r-l+1)%MOD;add[k]=0;multiply[k]=1;set[k]=z;return;}int mid=(l+r)>>1;pushdown(k,l,r);if(x<=mid) interval_set(k<<1,l,mid,x,y,z);if(y>mid) interval_set(k<<1|1,mid+1,r,x,y,z);update(k); 
}ll query(int k,int l,int r,int x,int y,int z)
{if(l>=x && r<=y){if(z==1)return tree[k].a%MOD;if(z==2)return tree[k].aa%MOD;if(z==3)return tree[k].aaa%MOD;}int mid=(l+r)>>1;ll ans=0;pushdown(k,l,r);if(x<=mid) ans=(ans+query(k<<1,l,mid,x,y,z))%MOD;if(y>mid) ans=(ans+query(k<<1|1,mid+1,r,x,y,z))%MOD;return ans;
}void search_point(int k,int l,int r,int x)
{if(l==r && l==x){t=tree[k].a;return;}pushdown(k,l,r);int mid=(l+r)>>1;if(x<=mid) search_point(k<<1,l,mid,x);else search_point(k<<1|1,mid+1,r,x);
}void test()
{for(int i=1;i<=n;i++){search_point(1,1,n,i);printf("%lld ",t);}printf("\n");
}int main()
{ll cmd,u,v,w;while(~scanf("%d%d",&n,&m) && (n||m)){memset(tree,0,sizeof(tree));memset(set,0,sizeof(set));memset(add,0,sizeof(add));for(int i=0,j=n<<2;i<=j;i++) multiply[i]=1;for(int i=0;i<m;i++){scanf("%lld%lld%lld%lld",&cmd,&u,&v,&w);if(cmd==1){interval_add(1,1,n,u,v,w%MOD);}else if(cmd==2){interval_multiply(1,1,n,u,v,w%MOD);}else if(cmd==3){interval_set(1,1,n,u,v,w%MOD);}else if(cmd==4){//test();printf("%lld\n",query(1,1,n,u,v,w));}}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384144.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)

http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1. 主版本模板类 首先我们来看一段初学者都能看懂&#xff0c;应用了模板的程序&#xff1a; 1 #include <iostream>2 using namespace std;3 4 template<class T1, class T2>5 clas…

使用openssl的md5库

http://blog.csdn.net/sinat_35297665/article/details/78244523 在linux机器上&#xff0c;有一个命令可以计算出文件的md5值&#xff0c;那就是md5sum&#xff0c;如果没有的话&#xff0c;就需要安装RPM包&#xff1a;coreutils。 现在我们使用openssl的库也可以方便的计算出…

Socket网络编程--小小网盘程序(1)

http://www.cnblogs.com/wunaozai/p/3886588.html 这个系列是准备讲基于Linux Socket进行文件传输。简单的文件传输就是客户端可以上传文件&#xff0c;可以从服务器端下载文件。就这么两个功能如果再加上身份验证&#xff0c;就成了FTP服务器了&#xff0c;如果对用户的操作再…

HDU - 4348To the moon——主席树+区间修改

HDU - 4348To the moon 【题目描述】 【题目分析】 题目中说明每次更新后时间都会加1&#xff0c;而且还会需要查询以前的区间&#xff0c;还会需要返回以前的时间&#xff0c;所以是很裸的主席树。区间查询的话我们同样需要用到lazy标记 通过这道题我发现线段树的操作还是很灵…

进入一个目录需要那些权限

1.文件访问者的分类 文件的访问者具体可分为以下几类&#xff1a; (1)拥有者 (2)组拥有者 (3)其他用户 这些都代表什么意思呢&#xff1f; 其中r表示只读&#xff0c;w表示只写&#xff0c;x表示可执行&#xff0c;第一个字母代表了文件的类型&#xff0c;其中文件类型可以分为…

Socket网络编程--小小网盘程序(2)

http://www.cnblogs.com/wunaozai/p/3887728.html 这一节将不会介绍太多的技术的问题&#xff0c;这节主要是搭建一个小小的框架&#xff0c;为了方便接下来的继续编写扩展程序。本次会在上一小节的基础上加上一个身份验证的功能。 因为网盘程序不像聊天程序&#xff0c;网盘是…

Linux下的重要目录

1.bin目录 主要防止系统下的各种必备可执行文件 2./proc 目录 这个目录相当于Windows下的计算机系统信息查看以及进程动态查看&#xff0c;可以查看计算机信息&#xff0c;用来存放当前计算机上的进程信息 3./sys 目录 (1)其中block目录用于存放块设备文件 (2)bus存放总线类型…

HDU - 6278 Just $h$-index主席树+二分

HDU - 6278 Just hhh-index 【题目描述】 【题目分析】 题目要求在区间[l,r][l,r][l,r]内大于h的数不少于h个&#xff0c;对于这种最大化问题&#xff0c;我们应该想到二分。 最小情况显然是1.最大情况显然是r−l1r-l1r−l1&#xff0c;对于一个hhh&#xff0c;我们如何判断能…

Socket网络编程--小小网盘程序(3)

http://www.cnblogs.com/wunaozai/p/3891062.html 接上一小节&#xff0c;这次增加另外的两张表&#xff0c;用于记录用户是保存那些文件。增加传上来的文件的文件指纹&#xff0c;使用MD5表示。 两张表如下定义: 1 create table files(2 fid int,3 filename varchar(64),4 md…

LInux下du, df, top, free, pstack, su, sudo, adduser, password命令

1.du命令&#xff1a;du [选项] 文件 (1)功能该命令是显示指定文件以及下的所有文件占用系统数据块的情况&#xff0c;如果没有文件&#xff0c;默认为是当前工作目录 -a    显示所有文件对系统数据块的使用情况 -b    显示数据块大小时以字节为基本单位 -c    除了显…

HDU - 5919 Sequence II——主席树+区间种类++逆序建树

【题目描述】 HDU - 5919 Sequence II 【题目分析】 题目给定一个数组&#xff0c;每次查询一个区间&#xff0c;找出区间内不同数字的个数x&#xff0c;然后输出按出现顺序第x/2向上取整个数字的位置。 按照要求&#xff0c;我们首先需要能够找出给定区间不同的数字个数。 首…

Socket网络编程--小小网盘程序(4)

http://www.cnblogs.com/wunaozai/p/3892729.html 在这一小节中实现了文件的下载&#xff0c;具体的思路是根据用户的uid和用户提供的文件名filename联合两张表&#xff0c;取得md5唯一标识符&#xff0c;然后操作这个标识符对应的文件发送给客户端。 实现下载的小小网盘程序 …

静态顺序表的实现

实现对顺序表的初始化&#xff0c;头插&#xff0c;头删&#xff0c;尾插&#xff0c;尾删&#xff0c; 任意下标的删除&#xff0c; 任意下标处的的元素删除&#xff0c;任意下标处的元素插入&#xff0c;任意元素的下标返回&#xff0c;任意下标处的元素返回&#xff0c; 删除…

树链剖分入门+HYSBZ - 1036树的统计Count

今天学习了树链剖分&#xff0c;记录一下。 【题目背景】 HYSBZ - 1036树的统计Count 【题目分析】 题目要求求任意结点之间路径的和以及路径上最大的结点&#xff0c;还有可能修改。如果正常做可能会很复杂&#xff08;我也不知道正常应该怎么做&#xff0c;应该要用到LCA什么…

Socket网络编程--小小网盘程序(5)

http://www.cnblogs.com/wunaozai/p/3893469.html 各位好呀&#xff01;这一小节应该就是这个小小网盘程序的最后一小节了&#xff0c;这一节将实现最后的三个功能&#xff0c;即列出用户在服务器中的文件列表&#xff0c;还有删除用户在服务器中的文件&#xff0c;最后的可以共…

进程相关概念

1.进程相关概念 进程是代码的一次动态执行&#xff0c;担当分配系统资源的角色&#xff0c;进程信息是被放在一个一个数据结构中&#xff0c;是一个结构体task_struct 2.进程控制块内容 //linux下的进程控制块 struct task_struct {volatile long state;// 说明了该进程是否可以…

SPOJ - QTREE3Query on a tree again!——树链剖分

【题目描述】 SPOJ - QTREE3Query on a tree again! 【题目分析】 题目要求是输出从111到xxx的路径上遇到的第一个黑色的点。我们可以用树链剖分&#xff08;不了解的同学请出门左拐&#xff0c;详见树链剖分入门&#xff09; 我们用线段树维护每个区间第一次遇到黑点的位置&a…

C++中的函数指针和函数对象总结

http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html 篇一、函数指针 函数指针&#xff1a;是指向函数的指针变量&#xff0c;在C编译时&#xff0c;每一个函数都有一个入口地址&#xff0c;那么这个指向这个函数的函数指针便指向这个地址。 函数指针的用途是很…

开发工具

1.编辑器 &#xff08;1&#xff09;vim     vim是从vi发展出来的一个文本编辑器。代码补完、编译错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用。 &#xff08;2&#xff09;sed     sed是一种流编辑器&#xff0c;它一次处理一行内容。处理时…

c++ 智能指针用法详解

http://www.cnblogs.com/TenosDoIt/p/3456704.html 本文介绍c里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c11支持&#xff0c;并且第一个已经被c11弃用。 为什么要使用智能指针&#xff1a;我们知道c的内存管理是让很多人头疼的事&#xff0…