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

题意:给出 n 个数,有三种操作,把区间的 ai 变为 φ(ai);把区间的 ai 变为 x;查询区间和。

题解:因为一个数由 ai 变为 φ(ai)在 log 次之后会变为 1 并且一直都为 1,考虑在没有第二种操作的情况下,只需要暴力修改记录区间最大值是否大于 1 即可。在加入第二个操作之后,可以发现对区间进行修改的话,一个区间内的数都是相同的,进行第一个操作可以对整个区间进行操作,故可以用线段树多记录一个区间内的数是否相同即可。

 #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 0x3f3f3f3f;
const double eps = 1e-;
const int MAXN = 3e5 + ;
const int MAXM = 1e7 + ;
const ll mod = 1e9 + ; bool check[MAXM];
int phi[MAXM], prime[MAXM / ], tot; void init(int N) {
tot = ;
phi[] = ;
for(int i = ; i <= N; i++) {
if(!check[i]) {
prime[tot++] = i;
phi[i] = i - ;
}
for(int j = ; j < tot; j++) {
if(i * prime[j] > N) break;
check[i * prime[j]] = true;
if(i % prime[j] == ) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
} else phi[i * prime[j]] = phi[i] * (prime[j] - );
}
}
} int a[MAXN],num[MAXN<<];
ll sum[MAXN<<]; void pushup(int rt) {
sum[rt] = sum[rt<<] + sum[rt<<|];
if(num[rt<<] == num[rt<<|]) num[rt] = num[rt<<];
else num[rt] = ;
// num[rt] = (num[rt<<1] == num[rt<<1|1]) ? num[rt] : 0;
} void build(int rt,int l,int r) {
if(l == r) {
sum[rt] = num[rt] = a[l];
return ;
}
int mid = (l + r) >> ;
build(rt<<,l,mid);
build(rt<<|,mid + ,r);
pushup(rt);
} void pushdown(int rt,int l,int r) {
if(num[rt]) {
int mid = (l + r) >> ;
num[rt<<] = num[rt<<|] = num[rt];
sum[rt<<] = 1ll * num[rt<<] * (mid - l + );
sum[rt<<|] = 1ll * num[rt<<|] * (r - mid);
num[rt] = ;
}
} void update1(int rt,int l,int r,int ql,int qr) {
if(ql > qr) return ;
if(num[rt] && l == ql && r == qr) {
num[rt] = phi[num[rt]];
sum[rt] = 1ll * num[rt] * (r - l + );
return ;
}
pushdown(rt,l,r);
int mid = (l + r) >> ;
if(qr <= mid) update1(rt<<,l,mid,ql,qr);
else if(ql > mid) update1(rt<<|,mid + ,r,ql,qr);
else {
update1(rt<<,l,mid,ql,mid);
update1(rt<<|,mid + ,r,mid + ,qr);
}
pushup(rt);
} void update2(int rt,int l,int r,int ql,int qr,int val) {
if(ql > qr) return ;
if(l == ql && r == qr) {
num[rt] = val;
sum[rt] = 1ll * num[rt] * (r - l + );
return ;
}
pushdown(rt,l,r);
int mid = (l + r) >> ;
if(qr <= mid) update2(rt<<,l,mid,ql,qr,val);
else if(ql > mid) update2(rt<<|,mid + ,r,ql,qr,val);
else {
update2(rt<<,l,mid,ql,mid,val);
update2(rt<<|,mid + ,r,mid + ,qr,val);
}
pushup(rt);
} ll query(int rt,int l,int r,int ql,int qr) {
if(ql == l && qr == r) return sum[rt];
pushdown(rt,l,r);
int mid = (l + r) >> ;
if(qr <= mid) return query(rt<<,l,mid,ql,qr);
else if(ql > mid) return query(rt<<|,mid + ,r,ql,qr);
else return query(rt<<,l,mid,ql,mid) + query(rt<<|,mid + ,r,mid + ,qr);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
init(1e7);
int t;
scanf("%d",&t);
while(t--) {
int n,m;
scanf("%d%d",&n,&m);
for(int i = ; i <= n; i++) scanf("%d",&a[i]);
build(,,n);
while(m--) {
int op,l,r,x;
scanf("%d",&op);
if(op == ) {
scanf("%d%d",&l,&r);
update1(,,n,l,r);
} else if(op == ) {
scanf("%d%d%d",&l,&r,&x);
update2(,,n,l,r,x);
} else if(op == ) {
scanf("%d%d",&l,&r);
printf("%lld\n",query(,,n,l,r));
}
}
}
return ;
}

HDU 5634 (线段树)的更多相关文章

  1. HDU 5634 线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5634 题意:给定一个长度为n的序列,有m次操作.操作有3种: 1 l,r :区间[l,r]的值变成ph ...

  2. 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 ...

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

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

  4. hdu 3436 线段树 一顿操作

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

  5. hdu 3397 线段树双标记

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

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

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

  7. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

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

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

  9. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  10. hdu 1542 线段树扫描(面积)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

随机推荐

  1. Java编程思想(三)控制程序流程

    3.1.10逗号运算符 我们可以使用一系列由逗号分隔的语句,而且哪些语句均会独立执行. 3.1.15复习计算顺序

  2. [转帖]tr命令的用法

    tr命令的用法 https://www.cnblogs.com/bingguoguo/articles/9188703.html tr命令   tr命令可以对来自标准输入的字符进行替换.压缩和删除.它 ...

  3. [转帖]Linux systemd 常用命令

    Linux systemd 常用命令 https://www.cnblogs.com/tsdxdx/p/7288490.html systemctl hostnamectl timedatectl l ...

  4. 浅谈>/dev/null 2>&1

    在crond计划任务.nohup中我们经常可以看到>/dev/null 2>&1,但是很多人并不理解其含义,想要真正的理解它,首先我们需要知道文件描述符的三种类型. 类型 文件描述 ...

  5. fiddler模拟发送请求和响应

    iddler模拟发送请求和响应 一.fiddler模拟发送请求 1.fiddler模拟发送get请求 1)例如:访问博客园https://www.cnblogs.com/,并且登录输入密码账号登录,再 ...

  6. redis集群(多机)分布

    一.实现原理 一致性哈希算法(Consistent Hashing): http://www.zsythink.net/archives/1182 二.配置两个redis服务,端口号要不一致 三.代码 ...

  7. 3-MySQL DBA笔记-开发基础

    第二部分 开发篇 本篇首先讲述数据库开发的一些基础知识,如关系数据模型.常用的SQL语法.范式.索引.事务等,然后介绍编程开发将会涉及的数据库的一些技巧,最后结合生产实际,提供一份开发规范供大家参考. ...

  8. c#连接数据库SqlHelper报错

    这是一个困扰了我好几天的问题,首先看一下报错信息 代码: private static string connectionString = ConfigurationManager.Connectio ...

  9. c#将电脑时间同步到网络时间

    最近遇到个项目,需要控制软件使用时间,由于电脑不联网可以修改时间,故需要联网使电脑同步网络时间 网上寻找了很多解决方案,代码如下: //Forproc_Win32.cs//对常用Win32 API函数 ...

  10. intellij IDE 破解 简单 License server 法

    http://idea.iteblog.com/key.php