题目链接: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. jQ全选或取消全选

    function checkAll(chkobj) {        if ($(chkobj).children("span").text() == "全选" ...

  2. python基础-11 socket,IO多路复用,select伪造多线程,select读写分离。socketserver源码分析

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  3. [Python3] 017 字典的内置方法

    目录 1. Python3 中如何查看 dict() 的内置方法 2. 少废话,上例子 (1) 清理大师 clear() (2) 拷贝君 copy() (3) get(key, default=Non ...

  4. 将java项目转换成javaWeb项目

    1.Ctrl+Shift+R快捷键:找到此项目中的.project文件,打开修改文件内容 在<natures> </natures>代码标签中,添加些内容: <natur ...

  5. 解决MarkDown打开出现:awesomium web-brower framework This view has crashed

    当在windows 8 以上操作系统安装markdown 的时候,可能会出现这样的错误 解决方法: 官网链接:http://markdownpad.com/faq.html#livepreview-d ...

  6. vps配置ipv6地址

    1.修改配置文件 vim /etc/network/interfaces 2.添加以下内容 auto he-ipv6 iface he-ipv6 inet6 v4tunnel address 2001 ...

  7. [面試題]C符號的優先順序

    int x = 0; if (x = 0 || x == 0) printf("%dn", x); printf("%dn", x); 參考C的優先表, 其實就 ...

  8. 全面优化MySQL(一)

    mysql执行一条查询语句的内部执行过程 权限验证 客户端通过连接器连接到 MYSQL服务器. 查询缓存 查询是否有查询缓存, 如果有缓存(之前执行过此语句),则直接返回缓存数据. 语法检查 分析器会 ...

  9. 2019-3-6-WPF-使用-SharpDX

    title author date CreateTime categories WPF 使用 SharpDX lindexi 2019-03-06 16:52:37 +0800 2018-4-20 9 ...

  10. 线上nginx 平滑添加新模块;如(--with-http_realip_module)

    nginx 添加模块1.查看当前nginx信息(配置文件路径,启动用户...) ps aux | grep nginx 2.查看当前nginx已启用的模块(记录模块信息,安装路径)./nginx -V ...