HDU 5634 线段树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5634
题意:给定一个长度为n的序列,有m次操作。操作有3种:
1 l,r :区间[l,r]的值变成phi[val[i]](l<=i<=r; phi是欧拉值)
2 l,r,x:区间[l,r]的值变成x
3 l,r:求区间[l,r]的和
思路:操作2和3就是传统的简单线段树,操作2对应区间覆盖,操作3对应区间求和,重点在于操作1,由于一个数经过不超过log次求phi后会变成1,所以可以在线段树是用一个same标记,如果整个区间的数都相同则操作1就转换成操作2的区间覆盖了。如果操作的区间[l,r]已经包含住当前递归的子树区间但是子树的same标记为假则继续递归到子树的same标记为真为止,最多递归到叶子结点。
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<time.h>
#include<cmath>
using namespace std;
typedef long long int LL;
#define L(k)(k<<1)
#define R(k)(k<<1|1)
const LL INF = ;
const int MAXN = 3e5 + ;
const int MAXX = 1e7 + ;
struct Node{
int l, r, val;
LL sum;
bool same;
Node(int _l = , int _r = , int _val = , LL _sum = , bool _same = false){
l = _l; r = _r; sum = _sum; same = _same; val = _val;
}
}Seg[MAXN * ];
int val[MAXN], Phi[MAXX];
void pushUp(int k){
Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
if (Seg[L(k)].val == Seg[R(k)].val&&Seg[L(k)].same&&Seg[R(k)].same&&Seg[L(k)].val != -){
Seg[k].same = true;
Seg[k].val = Seg[L(k)].val;
}
else{
Seg[k].same = false;
Seg[k].val = -;
}
}
void pushDown(int k){
if (Seg[k].same){
Seg[L(k)].same = Seg[R(k)].same = true;
Seg[L(k)].val = Seg[R(k)].val = Seg[k].val;
Seg[L(k)].sum = 1LL * (Seg[L(k)].r - Seg[L(k)].l + )*Seg[L(k)].val;
Seg[R(k)].sum = 1LL * (Seg[R(k)].r - Seg[R(k)].l + )*Seg[R(k)].val;
}
}
void Build(int st, int ed, int k){
Seg[k].l = st; Seg[k].r = ed; Seg[k].same = false; Seg[k].val = -;
if (st == ed){
Seg[k].val = val[st];
Seg[k].sum = val[st];
Seg[k].same = true;
return;
}
int mid = (st + ed) >> ;
Build(st, mid, L(k)); Build(mid + , ed, R(k));
pushUp(k);
}
void Change(int st, int ed, int val, int k){
if (Seg[k].l == st&&Seg[k].r == ed){
Seg[k].same = true;
Seg[k].val = val;
Seg[k].sum = 1LL * (ed - st + )*val;
return;
}
pushDown(k);
if (Seg[L(k)].r >= ed){
Change(st, ed, val, L(k));
}
else if (Seg[R(k)].l <= st){
Change(st, ed, val, R(k));
}
else{
Change(st, Seg[L(k)].r, val, L(k));
Change(Seg[R(k)].l, ed, val, R(k));
}
pushUp(k);
}
void Modify(int st, int ed, int k){
if (Seg[k].l == st&&Seg[k].r == ed&&Seg[k].same){
Seg[k].val = Phi[Seg[k].val];
Seg[k].sum = 1LL * (ed - st + )*Seg[k].val;
return;
}
pushDown(k);
if (Seg[L(k)].r >= ed){
Modify(st, ed, L(k));
}
else if (Seg[R(k)].l <= st){
Modify(st, ed, R(k));
}
else{
Modify(st, Seg[L(k)].r, L(k));
Modify(Seg[R(k)].l, ed, R(k));
}
pushUp(k);
}
LL Query(int st, int ed, int k){
if (Seg[k].l == st&&Seg[k].r == ed){
return Seg[k].sum;
}
pushDown(k);
if (Seg[L(k)].r >= ed){
return Query(st, ed, L(k));
}
else if (Seg[R(k)].l <= st){
return Query(st, ed, R(k));
}
else{
return Query(st, Seg[L(k)].r, L(k)) + Query(Seg[R(k)].l, ed, R(k));
}
pushUp(k);
}
void GetPhi(){ //预处理欧拉值
memset(Phi, , sizeof(Phi));
Phi[] = ;
for (LL i = ; i < MAXX; i++){
if (!Phi[i]){
for (LL j = i; j < MAXX; j += i){
if (!Phi[j]) Phi[j] = j;
Phi[j] = Phi[j] / i*(i - );
}
}
}
}
int main(){
//#ifdef kirito
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
//#endif
// int start = clock();
int n, t, m; GetPhi();
scanf("%d", &t);
while (t--){
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++){
scanf("%d", &val[i]);
}
Build(, n, );
for (int i = ; i <= m; i++){
int tpe, l, r, x;
scanf("%d%d%d", &tpe, &l, &r);
if (tpe == ){
Modify(l, r, );
}
else if (tpe == ){
scanf("%d", &x);
Change(l, r, x, );
}
else{
printf("%lld\n", Query(l, r, ));
}
}
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}
HDU 5634 线段树的更多相关文章
- 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 ...
- hdu 3974 线段树 将树弄到区间上
Assign the task Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 3436 线段树 一顿操作
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- hdu 3397 线段树双标记
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 4578 线段树(标记处理)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others) ...
- hdu 4533 线段树(问题转化+)
威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- hdu 2871 线段树(各种操作)
Memory Control Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- hdu 4052 线段树扫描线、奇特处理
Adding New Machine Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 1542 线段树扫描(面积)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
随机推荐
- layer-框架使用修改部分
关于框架中js调子方法出错的处理 top.layer.open({ id: options.id, type: 2, shade: options.shade, title: options.titl ...
- SpringBoot---事务支持
1.自动配置的事务管理器 1.1.使用JDBC 作为 数据访问技术 时,SpringBoot 为我们 定义了 PlatformTransactionManager的实现 DataSourc ...
- intraweb首次与LayUI结合
intraweb可以说是Delphi Web开发的好帮手,但是自带的控件搭建页面,感觉不是那么美观,于是想引用一个UI框架,Delphi来提供后台访问,但是发现一个问题,如果intraweb用模版,L ...
- Linux内核设计与实现 总结笔记(第二章)
一.Linux内核中的一些基本概念 内核空间:内核可独立于普通应用程序,它一般处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限.这种系统态和被保护起来的内存空间,称为内核空间. 进程上下文:当 ...
- 科讯使用的:ckeditor编辑器.复制word图片.一直沾不上去.谁有好的解决办法呢
在之前在工作中遇到在富文本编辑器中粘贴图片不能展示的问题,于是各种网上扒拉,终于找到解决方案,在这里感谢一下知乎中众大神以及TheViper. 通过知乎提供的思路找到粘贴的原理,通过TheViper找 ...
- Queue1循环队列
循环队列 1 #include<iostream> using namespace std; //#define maxSize 20 template <class T> c ...
- BUUCTF | [RoarCTF 2019]Easy Calc
看一下页面源码,发现了提示: calc.php?num=encodeURIComponent($("#content").val()) $("#content" ...
- js 通过浏览器直接打开应用程序(IOS,Android)
实现效果 如下图所示,在手机浏览器中访问京东的手机版网站(m.jd.com),顶部会有一个广告图,点击这个广告图,如果手机上已经安装了京东App,则直接打开,如果没有安装,则开始下载. 实现方式 1. ...
- 虚拟机安装linux遇到的问题
1.运行 yum -y update,提示没有权限,改为sudo yum -y update后,提示没有已启用的仓库.网上查找发现没有yum的库,然后开始安装yum. sudo apt-get in ...
- oracle SQL in plsql
刚安装好的oracle和plsql,以oracle11g为例 1.刚安装好后有两个默认的系统账号和初始密码:sys/change_on_install,system/manager 2.如果忘记了或不 ...