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 ...
随机推荐
- ZenCoding Syntax
语法: 后代:> 缩写:nav>ul>li 兄弟:+ 缩写:div+p+bq 上级:^ 缩写:div+div>p>span+em^bq 缩写:div+div>p&g ...
- Android学习-----如何使用sqlite对于后台数据交换,sqlite使用例程入门
SQLite 这是一个非常流行的嵌入式数据库.它支持 SQL 查询,和只使用很少的内存.Android 在集成实施 SQLite,所以每 Android 应用程序能够使用 SQLite 数据库. ...
- maven项目配置Project Facets时further configuration available不出来问题
如果下边的 further configuration available不出来 把Dynamic web module 去掉勾选,应用与项目,然后再点开项目的properties,再选中Dynami ...
- Web Api集成Swagger
WebApi集成Swagger 1.新建一个WebApi空项目 2.新建一个Person实体类: public class Person { public int ID { get; set; } p ...
- Gulp.js简介
Gulp.js简介 我们讨论了很多关于怎么减少页面体积,提高重网站性能的方法.有些是操作是一劳永逸的,如开启服务器的gzip压缩,使用适当的图片格式,或删除一些不必要的字符.但有一些任务是每次工作都必 ...
- Shell编程中Shift的用法(转)
位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shift命令相当于shift 1. 非常 ...
- 【编程之美】java二进制实现重建
package com.cn.binarytree.utils; /** * @author 刘利娟 liulijuan132@gmail.com * @version 创建时间:2014年7月20日 ...
- Python 分析Twitter用户喜爱的推文
CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-8-5 @author: guaguastd @name: an ...
- 在Windows下搭建React Native Android开发环境
widows版本: win7 64位 专业版 1. 安装jdk.(我用的jdk7) 注意选择x86还是x64版本, 添加到系统PATH环境变量 2. 准备好android sdk 这个不多说,同时推荐 ...
- 北京联通100M光纤宽带需邀请函 实际速率12MB/S - OFweek光通讯网
[新提醒]随身wifi无法使用FAQ(不断更新中~~~~~~) - 使用问题 - 360官方论坛 undefined 北京联通100M光纤宽带需邀请函 实际速率12MB/S - OFweek光通讯网 ...