Transformation

Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)
Total Submission(s): 4095    Accepted Submission(s): 1008

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
/*
hdu 4578 线段树(标记处理) 给你n个初始化为0的数进行以下操作:
1 x y c 给[x,y]上的数全加上c add
2 x y c 给[x,y]上的数全乘上c mult
3 x y c 将[x,y]上面的数全置为c same
4 x y c 查询[x,y]上所有数的c次方的和,然后对10007取模 首先我们可以发现 加法和乘法都无法直接维护我们想要的到的立方和,但对于same而言
sum = (r-l+1)*(tree[i].same^p).
如果每次查询我们都查找到单点,有极大的可能TLE。所以考虑查询的时候直接查找same标记,而且p也很小。
然后就是如何处理add,mult,same这三个标记的冲突.
就是same而言,更新到一个区间,那么先前这个区间上的所有标记都会作废
对于add和mult很明显会冲突,到后面你并不能知道是先处理add还是mult.所以
add和mult不能同时共处一个区间,而且先前到达的标记要先更新下去. 于是对于add和mult分3种情况: //就add而言
1.如果当前区间有same,那愉快地更新same就好了
2.如果当前区间有mult,那先对当前区间进行update_down,把mult标记先更新下去
3.如果只有add这个标记,那么更新一下即可 感觉就标记下放这方面,主要是注意标记相互之间的影响。
hhh-2016-04-04 09:41:07
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
#define lson (i<<1)
#define rson ((i<<1)|1)
typedef long long ll;
const int mod = 10007;
const int maxn = 100050;
struct node
{
int l,r;
ll mult,add,same;
int mid()
{
return (l+r)>>1;
}
int len()
{
return (r-l+1) ;
}
} tree[maxn<<2]; void update_up(int i)
{
} void build(int i,int l,int r)
{
tree[i].l = l,tree[i].r = r;
tree[i].mult=1;
tree[i].add=0;
tree[i].same = -1;
if(l == r)
{
tree[i].same = 0;
return ;
}
build(lson,l,tree[i].mid());
build(rson,tree[i].mid()+1,r);
update_up(i);
} void update_down(int i)
{
if(tree[i].same != -1)
{
tree[lson].add = tree[rson].add = 0;
tree[lson].mult= tree[rson].mult = 1;
tree[lson].same = tree[rson].same = tree[i].same;
tree[i].same = -1;
}
if(tree[i].add)
{
if(tree[lson].same != -1)
tree[lson].same = (tree[lson].same+tree[i].add)%mod;
else if(tree[lson].mult > 1)
{
update_down(lson);
tree[lson].add = tree[i].add;
}
else
tree[lson].add = (tree[lson].add+tree[i].add)%mod;
if(tree[rson].same != -1)
tree[rson].same = (tree[rson].same+tree[i].add)%mod;
else if(tree[rson].mult > 1)
{
update_down(rson);
tree[rson].add = tree[i].add;
}
else
tree[rson].add = (tree[rson].add+tree[i].add)%mod;
tree[i].add = 0;
}
if(tree[i].mult > 1)
{
if(tree[lson].same != -1)
tree[lson].same = (tree[lson].same*tree[i].mult)%mod;
else if(tree[lson].add)
{
update_down(lson);
tree[lson].mult = tree[i].mult;
}
else
tree[lson].mult = (tree[lson].mult*tree[i].mult)%mod;
if(tree[rson].same != -1)
tree[rson].same = (tree[rson].same*tree[i].mult)%mod;
else if(tree[rson].add)
{
update_down(rson);
tree[rson].mult = tree[i].mult;
}
else
tree[rson].mult = (tree[rson].mult*tree[i].mult)%mod;
tree[i].mult = 1;
}
} void update(int i,int l,int r,int flag,ll val)
{
if(tree[i].l >= l && tree[i].r <= r)
{
if(flag == 1)
{
if(tree[i].same != -1)
tree[i].same = (tree[i].same+val)%mod;
else if(tree[i].mult > 1)
{
update_down(i);
tree[i].add = val;
}
else
tree[i].add =(tree[i].add+val)%mod;
}
else if(flag == 2)
{
if(tree[i].same != -1)
tree[i].same = (tree[i].same*val)%mod;
else if(tree[i].add)
{
update_down(i);
tree[i].mult = val;
}
else
tree[i].mult = (tree[i].mult * val) %mod;
}
else if(flag == 3)
{
tree[i].same = val;
tree[i].same %= mod;
tree[i].add = 0;
tree[i].mult = 1;
}
return ;
}
int mid = tree[i].mid();
update_down(i);
if(l <= mid)
update(lson,l,r,flag,val);
if(r > mid)
update(rson,l,r,flag,val);
update_up(i);
} ll query(int i,int l,int r,int p)
{
if(tree[i].l == tree[i].r)
{
ll ans = 1;
for(int j =1; j <= p; j++)
ans =(ll)(ans*tree[i].same)%mod;
return ans%mod;
}
if(tree[i].l >= l && tree[i].r <= r && tree[i].same != -1)
{
ll ans = 1;
for(int j =1; j <= p; j++)
ans =(ll)(ans*tree[i].same)%mod;
ans = (ll)ans*(tree[i].len()%mod)%mod;
return ans%mod;
}
ll all = 0;
update_down(i);
int mid = tree[i].mid();
if(l <= mid)
all =(all+query(lson,l,r,p))%mod;
if(r > mid)
all = (all+query(rson,l,r,p))%mod;
return all;
} int main()
{
int t,n,m;
while(scanf("%d%d",&n,&m) && n && m)
{
build(1,1,n);
for(int i = 1; i <= m; i++)
{
int op,x,y;
ll c;
scanf("%d%d%d%I64d",&op,&x,&y,&c);
if(op <= 3)
update(1,x,y,op,c);
else
printf("%I64d\n",query(1,x,y,c));
}
}
return 0;
}

  

hdu 4578 线段树(标记处理)的更多相关文章

  1. hdu 3954 线段树 (标记)

    Level up Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  2. HDU 4578 线段树玄学算法?

    Transformation 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4578 Problem Description Yuanfang is p ...

  3. K - Transformation HDU - 4578 线段树经典题(好题)

    题意:区间  加   变成定值 乘  区间查询:和 平方和 立方和 思路:超级超级超级麻烦的一道题  设3个Lazy 标记分别为  change 改变mul乘 add加  优先度change>m ...

  4. HDU 4578 线段树复杂题

    题目大意: 题意:有一个序列,有四种操作: 1:区间[l,r]内的数全部加c. 2:区间[l,r]内的数全部乘c. 3:区间[l,r]内的数全部初始为c. 4:询问区间[l,r]内所有数的P次方之和. ...

  5. HDU - 4578 线段树+三重操作

    这道题自己写了很久,还是没写出来,也看了很多题解,感觉多数还是看的迷迷糊糊,最后面看到一篇大佬的才感觉恍然大悟. 先上一篇大佬的题解:https://blog.csdn.net/aqa20372995 ...

  6. hdu 4578 线段树 ****

    链接:点我  1

  7. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  8. hdu 2871 线段树(各种操作)

    Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  9. hdu 4267 线段树间隔更新

    A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K ...

随机推荐

  1. Basys3在线调试视频指南及代码

    fpga在线调试视频链接 FPGA选择型号:xc7a35tcpg236-1 des文件 `timescale 1ns / 1ps module top( output [1:0] led, outpu ...

  2. Something about SeekingJob---TelInterview(电话面试)

    昨天和今天分别收到两次电话面试,有一点小小感悟,遂注之. 作为一枚还未毕业的大三狗来说,我在想,找个实习真的是西天取金,必定要先经历九九八十一难吗(伤心)?所以在这里整理了电话面试遇到的问题: 集合框 ...

  3. JAVA_SE基础——34.static修饰成员变量

    需求:描述一下学校的学生.  特点:都是中国人.... 测试代码1: class Student{ String name; String country = "中国"; //国籍 ...

  4. 09_Python定义方法_Python编程之路

    有关Python判断与循环的内容我们上几节已经跟大家一起学习了,这一节我们主要针对def 做一个讲解 def 定义一个方法 在项目编程中,我们往往要做很多重复的事,比如一个排序的功能(当然Python ...

  5. Linux CentOS7.0 (04)systemctl vs chkconfig、service

    CentOS 7.0中已经没有service命令,而是启用了systemctl服务器命令 systemctl 是系统服务管理器命令,它实际上将 service 和 chkconfig 这两个命令组合到 ...

  6. python实现 多叉树 寻找最短路径

    完全原创,能力有限,欢迎参考,未经允许,请勿转载 ! 完全原创,能力有限,欢迎参考,未经允许,请勿转载 ! 完全原创,能力有限,欢迎参考,未经允许,请勿转载 ! 完全原创,能力有限,欢迎参考,未经允许 ...

  7. ubuntu下创建python的虚拟环境

    当我们在同一个机器上进行开发多个项目,每个项目于用到包的不同版本的时候,就很尴尬. 安装python包的命令是: sudo pip install 包名 这样的话,会将包安装到/usr/local/l ...

  8. Python基础数据类型之集合以及其他和深浅copy

    一.基础数据类型汇总补充 list  在循环一个列表时,最好不要删除列表中的元素,这样会使索引发生改变,从而报错(可以从后向前循环删除,这样不会改变未删元素的索引). 错误示范: lis = [,,, ...

  9. PHP 通过fsockopen函数获取远程网页源码

    <?php $fp = fsockopen("www.baidu.com", 80, &$errno, &$errstr, 10); if(!$fp) { e ...

  10. Python3NumPy——数组(2)之数学空间与NumPy空间

    0 介绍 本文承接上一篇,文章采用新的阐述方式,将数学中的表达与NumPy中的函数关联起来. 采用这种方式,可以直接建立数学表达与计算系统的对应关系,更易理解. 由于博客编写时间有限,每次尝试一个知识 ...