Transformation

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=4578

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

题意

给你一个序列,支持四种操作

1.区间加法

2.区间乘法

3.区间减法

4.求和,平方和,立方和 即\(\large \sum_{i=l}^{r}{a_i^p}(1\le p\le 3)\)

题解

一开始看到这道题,觉得可以用数学公式搞搞,搞了半天确实搞出了个公式,用sum1,sum2,sum3分别存和,平方和,立方和,然后合并的时候再搞

搞。但是感觉很麻烦,于是先上网查了查正解是不是有什么巧妙的方法。但是看完网上题解,我才发现都是用的玄学复杂度。

于是我就愉快地也跟着各位大佬一样玄学操作啦。

具体操作:还是用线段树,遇到一段连续相同的区间就可以马上得到答案,其余部分直接暴力就行,我寻思着只要先把每个数都变得不一样然后求所有数的立方和,直接就暴了(别想那么多,这题纯属娱乐)。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x7f7f7f7f
#define N 100050
#define mo 10007
ll n,m;
struct Node{ll l,r,lazy;};
struct segmentTree
{
Node tr[N<<2];
void push_up(ll x);
void push_down(ll x);
void bt(ll x,ll l,ll r);
void add(ll x,ll l,ll r,ll tt);
void multiply(ll x,ll l,ll r,ll tt);
void cover(ll x,ll l,ll r,ll tt);
ll query(ll x,ll l,ll r,ll tt);
}seg;
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void segmentTree::push_up(ll x)
{
if(tr[x].l==tr[x].r)return;
Node &a=tr[x<<1],&b=tr[x<<1|1];
if (a.lazy==b.lazy&&tr[x].lazy==-1)tr[x].lazy=a.lazy;
}
void segmentTree::push_down(ll x)
{
if (tr[x].lazy==-1)return;
tr[x<<1].lazy=tr[x].lazy;
tr[x<<1|1].lazy=tr[x].lazy;
tr[x].lazy=-1;
}
void segmentTree::bt(ll x,ll l,ll r)
{
tr[x]=Node{l,r,0};
if (l==r)return;
ll mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
}
void segmentTree::add(ll x,ll l,ll r,ll tt)
{
if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
{
tr[x].lazy+=tt;
tr[x].lazy%=mo;
return;
}
ll mid=(tr[x].l+tr[x].r)>>1;
push_down(x);
if (l<=mid)add(x<<1,l,r,tt);
if (mid<r)add(x<<1|1,l,r,tt);
push_up(x);
}
void segmentTree::multiply(ll x,ll l,ll r,ll tt)
{
if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
{
tr[x].lazy*=tt;
tr[x].lazy%=mo;
return;
}
ll mid=(tr[x].l+tr[x].r)>>1;
push_down(x);
if (l<=mid)multiply(x<<1,l,r,tt);
if (mid<r)multiply(x<<1|1,l,r,tt);
push_up(x);
}
void segmentTree::cover(ll x,ll l,ll r,ll tt)
{
if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
{
tr[x].lazy=tt%mo;
return;
}
ll mid=(tr[x].l+tr[x].r)>>1;
push_down(x);
if (l<=mid)cover(x<<1,l,r,tt);
if (mid<r)cover(x<<1|1,l,r,tt);
push_up(x);
}
ll segmentTree::query(ll x,ll l,ll r,ll tt)
{
if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
{
ll ans=1;
for(ll i=1;i<=tt;i++)ans*=tr[x].lazy;
ans*=(tr[x].r-tr[x].l+1);
return ans%mo;
}
ll mid=(tr[x].l+tr[x].r)>>1,ans=0;
push_down(x);
if(l<=mid)ans+=query(x<<1,l,r,tt);
if(mid<r)ans+=query(x<<1|1,l,r,tt);
push_up(x);
return ans%mo;
}
void work()
{
read(n); read(m);
if (n+m==0)exit(0);
seg.bt(1,1,n);
for(ll i=1;i<=m;i++)
{
ll id,x,y,tt;
read(id); read(x); read(y); read(tt);
if (id==1)seg.add(1,x,y,tt);
if (id==2)seg.multiply(1,x,y,tt);
if (id==3)seg.cover(1,x,y,tt);
if (id==4)printf("%lld\n",seg.query(1,x,y,tt));
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
while(1)work();
}

HDU 4578 线段树玄学算法?的更多相关文章

  1. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

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

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

  3. hdu 4578 线段树 ****

    链接:点我  1

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

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

  5. HDU 4578 线段树复杂题

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

  6. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  7. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  9. hdu 3397 线段树双标记

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

随机推荐

  1. GAN生成式对抗网络(二)——tensorflow代码示例

    代码实现 当初学习时,主要学习的这个博客 https://xyang35.github.io/2017/08/22/GAN-1/ ,写的挺好的. 本文目的,用GAN实现最简单的例子,帮助认识GAN算法 ...

  2. 图的基本存储的基本方式一(SDUT 3116)

    Problem Description 解决图论问题,首先就要思考用什么样的方式存储图.但是小鑫却怎么也弄不明白如何存图才能有利于解决问题.你能帮他解决这个问题么? Input 多组输入,到文件结尾. ...

  3. element-ui下拉按钮的用法

    <el-dropdown class="avatar-container" trigger="click"> <div class=" ...

  4. c语言 指针数组

    指针数组指针数组是数组,指针数组每个元素是一个指针指针数组的定义:type* parray[n]; type* 是数组中每个元素的类型parray 为数组名n为大小 例子:float* a[3] // ...

  5. SSRF漏洞攻击利用从浅到深

    梳理一下ssrf 不详细 简单记录 0x01 SSRF成因和基本利用0x02 内网打未授权redis0x03 关于ssrf打授权的redis0x04 写redis shell和密钥的一点问题0x05 ...

  6. 解析配置文件 redis.conf

    1.units单位 2.INCLUDES包含 3.GENERAL通用 1).daemonize daemonize yes 启用后台守护进程运行模式 2).pidfile pidfile /var/r ...

  7. pwn学习日记Day13 《程序员的自我修养》读书笔记

    重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程.它是实现多道程序在内存中同时运行的基础.重定位有两种,分别是动态重定位与静态重定位. 静态重定位:即在程序装入内存的过程中完成,是指 ...

  8. RISC-V riscv64-unknown-elf

    riscv64-unknown-elf 为 RISC-V指令集的交叉编译工具 以下环境在Liunx ubuntu x86_64 环境下进行,下面示例以生成32位文件为目标来操作使用. screen / ...

  9. git如何将一个远程仓库的某个分支拉取到当前分支?

    答: git pull <remote_repository_url> <branch_name> 例如: git clone https://github.com/lede- ...

  10. 005-多线程-锁-JUC锁-LockSupport【使用、Unsafe、对比Object的wait、底层源码】

    一.概述 在Java多线程中,当需要阻塞或者唤醒一个线程时,都会使用LockSupport工具类来完成相应的工作.LockSupport定义了一组公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能 ...