HDU4777 Rabbit Kingdom(树状数组)
来源:互联网 发布:淘宝ysl口红真假 编辑:程序博客网 时间:2024/06/05 09:35
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4777
题意:n个数,m个询问,每个询问是一个[L,R]区间,问你这个区间内,有几个数字与其他的数字互质。
思路:想了很久还是不会做,看了一些别人的博客,算是有点明白了。先求出2-200000里每个数字的素数因子(包括本身),然后用一个数组标记素数因子的位置,从左到右扫一遍,从右到左扫一遍,求出L[]和R[],表示每个位置的左边第一个与他不互质的数的位置,和右边第一个与他不互质的数的位置。求出L和R以后,就可以用树状数组来操作。我们可以知道一个特点,对于一个区间[L,R],我们只要用树状数组在L点+1,在R+1处-1,就可以使得[L,R]区间整体+1。我们通过L数组和R数组,可以知道,当前这个位置所起到与所有数字互质的作用范围是[L+1,R-1],但是我们要用求得答案的时候是要sum(R)-sum(L-1),所以我们直接用树状数组来操作[x(当前位置),R]区间就可以了。那么利用这个思路,我们把查询离线,按照查询的L从小到大排序。通过一个变量来表示当前扫描的位置,然后从左到右扫描同时遍历询问,我们用每一个左区间的位置来存放数字的位置,保存下一个表,那就能可以通过当前这个左区间得知哪些位置使用了这个左区间,然后扫描的时候就可以利用这个表来更新树状数组。
对于每一个询问,答案是sum(R)-sum(L-1)。
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <iostream>#include <vector>#include <map>#include <set>#include <queue>#include <ctime>using namespace std;typedef long long ll;typedef pair<int,int> pii;#define pb push_back#define mp make_pair#define lson l, m, rt << 1#define rson m + 1, r, rt << 1|1#define calm (l + r) >> 1const int INF = 1e9+7;const int N=200010;struct P{ int l,r,id;}input[N];int n,m,a[N],tree[N],l[N],r[N],p[N],ans[N];bool vis[N];vector<int> fac[N],pos[N];void init(){//预处理每个数字的素因子,包含本身 for(int i=2;i<=200000;i++){ if(!vis[i]){ fac[i].pb(i); for(int j=i+i;j<=200000;j+=i){ vis[j]=true; fac[j].pb(i); } } }}int sum(int x){ int ans=0; while(x){ ans+=tree[x]; x-=x&-x; } return ans;}void add(int x,int v){ while(x<=n){ tree[x]+=v; x+=x&-x; }}inline bool cmp(P a,P b){ return a.l<b.l;}int main(){ freopen("D://input.txt","r",stdin); init(); while(scanf("%d%d",&n,&m)!=EOF&&n&&m){ for(int i=1;i<=n;i++){ scanf("%d",&a[i]); pos[i].clear(); } for(int i=0;i<m;i++){ scanf("%d%d",&input[i].l,&input[i].r); input[i].id=i; } memset(tree,0,sizeof tree); memset(p,0,sizeof p); for(int i=1;i<=n;i++){//cal l[i] int now=0; for(int j=0,len=fac[a[i]].size();j<len;++j){ now=max(now,p[fac[a[i]][j]]); p[fac[a[i]][j]]=i; } l[i]=now; pos[now].pb(i);//在每个左区间,记录使用这个左区间的数字,便于扫描 } memset(p,127,sizeof p); for(int i=n;i>=1;i--){//cal r[i] int now=n+1; for(int j=0,len=fac[a[i]].size();j<len;++j){ now=min(now,p[fac[a[i]][j]]); p[fac[a[i]][j]]=i; } r[i]=now; } sort(input,input+m,cmp); for(int i=1;i<=n;i++){ if(l[i]<1){ add(i,1); if(r[i]<=n)add(r[i],-1); } } int cur=1;//作为扫描的位置标志 for(int i=0;i<m;i++){ while(cur<input[i].l){ add(cur,-1);//先把事先加上去的减去 if(r[cur]<=n)add(r[cur],1); for(int j=0,len=pos[cur].size();j<len;++j){//遍历使用了这个左区间的数字的位置,给他们的区间加上他们这个位置的贡献 add(pos[cur][j],1); if(r[pos[cur][j]]<=n)add(r[pos[cur][j]],-1); } ++cur; } ans[input[i].id]=sum(input[i].r)-sum(input[i].l-1); } for(int i=0;i<m;i++){ printf("%d\n",ans[i]); } } return 0;}
0 0
- HDU4777 Rabbit Kingdom 树状数组
- HDU4777 Rabbit Kingdom(树状数组)
- hdu4777 Rabbit Kingdom 离线树状数组 求询问区间内的区间数
- hdu4777 Rabbit Kingdom
- hdu 4777 Rabbit Kingdom(离线+树状数组)
- hdu 4777 Rabbit Kingdom 离线树状数组
- hdu 4777 Rabbit Kingdom(树状数组)
- [HDU 4777 Rabbit Kingdom] 离线+树状数组
- HDU 4777 Rabbit Kingdom(树状数组)
- hdu 4777 Rabbit Kingdom(树状数组)
- hdu 4777 Rabbit Kingdom 离线+树状数组
- Hdu 4777 Rabbit Kingdom 树状数组
- hdu 4777 Rabbit Kingdom(树状数组)
- HDU 4777 Rabbit Kingdom [离线+树状数组]
- HDU 4777 Rabbit Kingdom【树状数组】
- hdu 4777 Rabbit Kingdom 树状数组
- HDU 4777 Rabbit Kingdom(树状数组 离线)
- hdu-4777Rabbit Kingdom 树状数组
- pat 城市救援 最短路
- [Cloud Computing]Mechanisms: Application Delivery Controller
- 简单的CSS样板
- 恭喜发财,红包拿来
- 并发编程---Java并发容器原理原理剖析(一)ConcurrentHashMap
- HDU4777 Rabbit Kingdom(树状数组)
- clone和clone(true)的差别
- Servlet Filter
- AFHTTPRequestOperationManager在引入afnetworking后依然找不到
- DelayQueue 学习和应用
- Android Studio "佛祖保佑 永无bug" 注释模板设置详解(仅供娱乐)
- gcc/g++
- table前端分页
- 一种基于自定义控件的验证码