题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5634

--------------------------------------------------------------------------------------------

官方题解上给的是用平衡树写 不过用类似的思路 也是可以用线段树去写的

操作$2$区间赋为相同值可以直接按照常规的线段树的题目去写

操作$1$是只减不增的 而且最多$log$次会减少到$1$

所以大量使用$1$操作会出现许多连续的$1$

当访问到区间都是一个值显然可以直接返回结果

而在这之前我们变可以把区间不为相同值的进行暴力取$phi$

尽管操作$2$会使区间值增加 但如果把连续的相同值算作$1$个区间的话

操作$2$每次最多只会增加$1$个区间 所以均摊下来并不会使操作$1$的复杂度增加

最终复杂度也是$O((n + m)logn)$的

 #include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1e7, L = 7e5, T = 3e5 + ;
bool used[N + ];
int phi[N + ], p[L];
int a[T], flag[T << ];
long long sum[T << ];
int len, t, n, m;
void getprime()
{
phi[] = ;
for(int i = ; i <= N; ++i)
{
if(! used[i])
{
p[++len] = i;
phi[i] = i - ;
}
for(int j = ; j <= len && i * p[j] <= N; ++j)
{
used[i * p[j]] = ;
if(i % p[j] == )
{
phi[i * p[j]] = phi[i] * p[j];
break;
}
else
phi[i * p[j]] = phi[i] * (p[j] - );
}
}
}
void build(int x, int L, int R)
{
if(L == R)
{
sum[x] = flag[x] = a[L];
return;
}
int mid = (L + R) >> ;
build(x << , L, mid);
build(x << | , mid + , R);
sum[x] = sum[x << ] + sum[x << | ];
flag[x] = (flag[x << ] == flag[x << | ] ? flag[x << ] : );
}
void update2(int x, int L, int R, int tl, int tr, int y)
{
if(L <= tl && tr <= R)
{
flag[x] = y;
sum[x] = (long long)flag[x] * (tr - tl + );
return;
}
int mid = (tl + tr) >> ;
if(flag[x])
{
update2(x << , tl, mid, tl, mid, flag[x]);
update2(x << | , mid + , tr, mid + , tr, flag[x]);
}
if(L <= mid)
update2(x << , L, R, tl, mid, y);
if(mid < R)
update2(x << | , L, R, mid + , tr, y);
sum[x] = sum[x << ] + sum[x << | ];
flag[x] = (flag[x << ] == flag[x << | ] ? flag[x << ] : );
}
void update1(int x, int L, int R, int tl, int tr)
{
if(flag[x] && L <= tl && tr <= R)
{
flag[x] = phi[flag[x]];
sum[x] = (long long)flag[x] * (tr - tl + );
return;
}
int mid = (tl + tr) >> ;
if(flag[x])
{
update2(x << , tl, mid, tl, mid, flag[x]);
update2(x << | , mid + , tr, mid + , tr, flag[x]);
}
if(L <= mid)
update1(x << , L, R, tl, mid);
if(mid < R)
update1(x << | , L, R, mid + , tr);
sum[x] = sum[x << ] + sum[x << | ];
flag[x] = (flag[x << ] == flag[x << | ] ? flag[x << ] : );
}
long long query(int x, int L, int R, int tl, int tr)
{
if(L <= tl && tr <= R)
return sum[x];
int mid = (tl + tr) >> ;
if(flag[x])
{
update2(x << , tl, mid, tl, mid, flag[x]);
update2(x << | , mid + , tr, mid + , tr, flag[x]);
}
long long re = ;
if(L <= mid)
re += query(x << , L, R, tl, mid);
if(mid < R)
re += query(x << | , L, R, mid + , tr);
return re;
}
int main()
{
getprime();
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++i)
scanf("%d", &a[i]);
build(, , n);
int op, x, y, z;
while(m--)
{
scanf("%d%d%d", &op, &x, &y);
if(op == )
update1(, x, y, , n);
else if(op == )
{
scanf("%d", &z);
update2(, x, y, , n, z);
}
else
printf("%lld\n", query(, x, y, , n));
}
}
return ;
}

HDU 5634 Rikka with Phi的更多相关文章

  1. HDU 5634 Rikka with Phi 线段树

    题意:bc round 73 div1 D 中文题面 分析:注意到10^7之内的数最多phi O(log(n))次就会变成1, 因此可以考虑把一段相同的不为1的数缩成一个点,用平衡树来维护. 每次求p ...

  2. 2018.07.03 HDU Rikka with Phi(线段树)

    Rikka with Phi Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) P ...

  3. 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

    // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...

  4. HDU 6088 - Rikka with Rock-paper-scissors | 2017 Multi-University Training Contest 5

    思路和任意模数FFT模板都来自 这里 看了一晚上那篇<再探快速傅里叶变换>还是懵得不行,可能水平还没到- - 只能先存个模板了,这题单模数NTT跑了5.9s,没敢写三模数NTT,可能姿势太 ...

  5. HDU 5831 Rikka with Parenthesis II(六花与括号II)

    31 Rikka with Parenthesis II (六花与括号II) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536 ...

  6. HDU5634 Rikka with Phi 线段树

    // HDU5634 Rikka with Phi 线段树 // 思路:操作1的时候,判断一下当前区间是不是每个数都相等,在每个数相等的区间上操作.相当于lazy,不必更新到底. #include & ...

  7. Rikka with Phi 线段树

    Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds ...

  8. HDU 6091 - Rikka with Match | 2017 Multi-University Training Contest 5

    思路来自 某FXXL 不过复杂度咋算的.. /* HDU 6091 - Rikka with Match [ 树形DP ] | 2017 Multi-University Training Conte ...

  9. HDU 6093 - Rikka with Number | 2017 Multi-University Training Contest 5

    JAVA+大数搞了一遍- - 不是很麻烦- - /* HDU 6093 - Rikka with Number [ 进制转换,康托展开,大数 ] | 2017 Multi-University Tra ...

随机推荐

  1. Java基础/发起http和https请求

    Java中发起http和https请求 一般调用外部接口会需要用到http和https请求. 本案例为:前后端完全分离,前端框架(React+Mobx+Nornj),后端(Go语言). 面临问题:跨域 ...

  2. 基于Filter实现Gzip数据压缩

    在web开发中,当服务器端向客户端返回的数据量比较大时,我们可以通过Gzip对数据进行压缩处理 注意:如果小数据量进行压缩,压缩后的数据可能比原始数据还大:所以response返回数据量比较小时不推荐 ...

  3. Java-第N篇推荐的一些学习书籍

    1.推荐的一些学习书籍或者需要掌握的基本知识 book | |---ant | |---maven | |---git(菜鸟教程) | |---Dos shell | |---linux常用的命令.l ...

  4. web框架Django一

    一.django安装 # pip 安装 pip3 install Django # 克隆下载最新版本 git clone https://github.com/django/django.git # ...

  5. Python中yield和return两者之间区别

    在任何函数都有返回值,一般都是想到return 关键词,在函数生成器中有个关键词 yield 也可以做返回值,在函数没调用之前,是不会输出任何东西的 1,return 用法 def stu(): re ...

  6. .net easyui Tree树

    原文:https://www.cnblogs.com/hantianwei/archive/2012/03/19/2407118.html Tree 树   用 $.fn.tree.defaults ...

  7. 29、前端知识点--session\cookie\token

    Java Token的原理和生成使用机制 https://yq.aliyun.com/articles/594217 Cookies Session Token 三者区别及应用场景 https://w ...

  8. k3 cloud套打模板中绑定加税合价字段的时候数据都为空,不绑定的时候显示正常

    检查bos中加税合计字段,是不是关联币别绑定错误

  9. keepalived的配置文件

    ! Configuration File for keepalived global_defs { notification_email { # acassen@firewall.loc # fail ...

  10. ELK windows下部署测试

    操作系统 win7 (当时想在linux下部署,虚拟内存过小,转而在windows下) 版本说明 elasticsearch-6.6.2  (elasticsearch-head-master插件) ...