hdu(预处理+线段树)
给n个数,m个询问, 问任意区间内与其它数互质的数有多少个
比如3个数1 2 4,询问[1,3] 那么答案是1
千万要记住,这样的题目,如果你不转变下,使劲往线段树想(虽然转变之后,也说要用到线段树,但是维护的东西不同了),那么会发现这样的题目,区间与区间之间是无法传递信息的,
区间与区间是无法传递信息的,区间与区间之间是无法传递信息的,重要的东西说三遍。
设n个数,存在数组a[]里面
我们预处理出,L[],和R[],L[i] 表示从i往左,第一个与a[i]不互质的数的位置+1, R[i]表示从i往右,第一个与a[i]不互质的数的位置-1
即L[i] 表示 [L[i],i]内的所有数都与a[i]互质,R[i]表示[i,R[i]]内的所有数都与a[i]互质
然后我们离线处理,将所有的询问按照左端点排序
然后枚举左端点i,将所有L[j] = i的 [j,R[j]]区间+1,因为当左端点为i时,L[j]=i的数都在各自的有效区间[j,R[j]]里面生效了
当i=询问的区间的左端点时,只要查询右端点被加了多少次就行了。
走过i时,第i个数不再生效,所以将[i,R[i]]区间-1
#include<cstdio>
#include<iostream>
#include<string.h>
#include<algorithm>
#include <vector>
using namespace std;
const int N = + ;
vector<int> prime[N];
vector<int> cL[N];
int a[N],L[N],R[N];
int mark[N];
int tree[N<<],lazy[N<<];
int ans[N];
void pushDown(int rt)
{
if(lazy[rt])
{
lazy[rt<<] += lazy[rt];
lazy[rt<<|] += lazy[rt];
tree[rt<<] += lazy[rt];
tree[rt<<|] += lazy[rt];
lazy[rt] = ;
}
}
void update(int l, int r, int rt, int L, int R, int val)
{
if(L<=l && R>=r)
{
lazy[rt]+=val;
tree[rt] += val;
return;
}
pushDown(rt);
int mid = (l+r)>>;
if(L<=mid)
update(l,mid,rt<<,L,R,val);
if(R>mid)
update(mid+,r,rt<<|,L,R,val); }
int query(int l, int r, int rt, int pos)
{
if(l==r)
{
return tree[rt];
}
pushDown(rt);
int mid = (l+r)>>;
if(pos<=mid)
return query(l,mid,rt<<,pos);
else
return query(mid+,r,rt<<|,pos);
}
struct Node
{
int l,r,id;
bool operator<(const Node&rhs)const
{
return l < rhs.l;
}
}q[N]; void getPrime()
{
for(int i=;i<=;++i)
{
if(!mark[i])
for(int j=i;j<=;j+=i)
{
mark[j] = true;
prime[j].push_back(i);//得到j的所有素数因子i
}
}
}
void init(int n)
{
memset(mark,,sizeof(mark));
for(int i=; i<prime[a[]].size(); ++i)
mark[prime[a[]][i]] = ;
L[] = ;
cL[].push_back();
for(int i=;i<=n;++i)
{
int pos = ;
for(int j=; j<prime[a[i]].size(); ++j)
{
pos = max(pos,mark[prime[a[i]][j]]);
mark[prime[a[i]][j]] = i;
}
L[i] = pos + ;
cL[L[i]].push_back(i);
}
for(int i=;i<N;++i)mark[i] = n + ;
for(int i=;i<prime[a[n]].size(); ++i)
mark[prime[a[n]][i]] = n;
R[n] = n;
for(int i=n-;i>=;--i)
{
int pos = n + ;
for(int j=;j<prime[a[i]].size(); ++j)
{
pos = min(pos,mark[prime[a[i]][j]]);
mark[prime[a[i]][j]] = i;
}
R[i] = pos - ;
}
}
int main()
{
int n,m;
getPrime();
while(scanf("%d%d",&n,&m),n+m)
{
memset(tree,,sizeof(tree));
memset(lazy,,sizeof(lazy));
for(int i=;i<=n;++i)
{
scanf("%d",&a[i]);
cL[i].clear();
}
init(n);
for(int i=;i<m;++i)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id = i;
}
sort(q,q+m);
int cur = ;
//枚举左端点
for(int i=;i<=n;++i)
{
//当左端点为i时,使得所有L[j] = i的数都在各自的区间[j,R[j]]
//所以在[j,R[j]]区间+1
for(int j=;j<cL[i].size(); ++j)
update(,n,,cL[i][j],R[cL[i][j]],);
//当询问的左端点为i时,
while(q[cur].l==i)
{
//只要询问右端点的值就行了,因为每个数都在自己能生效的区间里面+1了
ans[q[cur].id] = query(,n,,q[cur].r);
cur++;
}
//要走过第i个数了,所以第i个数不再生效了,所以将[i,R[i]]区间-1
update(,n,,i,R[i],-);
}
for(int i=;i<m;++i)
printf("%d\n",ans[i]);
}
return ;
}
hdu(预处理+线段树)的更多相关文章
- 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 ...
随机推荐
- 手动配置S2SH三大框架报错(三)
十二月 08, 2013 10:24:43 下午 org.apache.catalina.core.AprLifecycleListener init 严重: An incompatible vers ...
- 使用TWebBrowser时存在内存泄漏问题的解决方案(使用SetProcessWorkingSetSize函数,或者修改OleCtrls.pas源码解决问题)
用TWebBrower不断打开多个网页,多某些版本的操作系统上运行一段时间后,发现占用系统内存达几百M,直到关闭程序后,占用的内存才能释放. 这个问题在网有很多讨论,比较多人的建议办法是用SetPro ...
- TFS2010安装与管理
整了几天TFS,把相关的一些配置与安装的要点简单记下,希望对大家有用.本篇主要是安装与配置上的内容,下一篇会介绍如何使用以及使用方面的相关心得体会. 本篇内容简要: 1. 安装部署 1.1. 流 ...
- Linux入门基础#2:Linux文件系统基本结构
本文出自 http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...
- 高级Bash脚本编程指南(27):文本处理命令(三)
高级Bash脚本编程指南(27):文本处理命令(三) 成于坚持,败于止步 处理文本和文本文件的命令 tr 字符转换过滤器. 必须使用引用或中括号, 这样做才是合理的. 引用可以阻止shell重新解释出 ...
- Mojo 分析日志接口
#!/usr/bin/perl #取文件行数 ##循环开始清空文件 use POSIX; use DBI; my $dir = '/data01/applog_backup'; my $file = ...
- JavaScript学习总结1
/***我是切割线 的開始***/ //利用prototype属性能够加入公有属性和方法 function myConstructor2(){ this.a='大灰狼'; }; //声明构造函数,能够 ...
- C#验证字符串是否是数字,是否包括中文,是否是邮箱格式,是否是电话格式
using System; using System.Web; using System.Text; using System.Web.UI.WebControls; ...
- Delaunay三角剖分算法
在图像处理中,经常会使用到三角剖分算法: 具体定义及其算法可以参考:http://baike.so.com/doc/5447649.html 下面放出来代码: Delaunay接口为存C: 测试是使用 ...
- Modular Fibonacci
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30506#problem/U fib数列对2^m取模的循环节为3*(2^(m-1)) #i ...