hdu 4777 Rabbit Kingdom 区间覆盖

来源:互联网 发布:网络摄像头监控软件 编辑:程序博客网 时间:2024/05/30 04:04
//hdu 4777 Rabbit Kingdom 区间覆盖////题目大意:////给n个数,有q个区间查询,求出[L,R]区间内有多少个互质的数////解题思路:////首先我们将问题转化,互质个数 = 总的个数 - 不互质的个数.//对于每个数,我们求一个L[i],R[i]表示分别到左右最近的与i不互质的//的数的位置.这个用扫描的方式,记录一下一个数因子出现的位置即可.//对于一个区间[L,R].我们对L[i],R[i]进行讨论.如果L[i]或者R[i]在当前//区间中,那么这个数一定是不合法的所以去掉这一个数.但是当L[i]和R[i]//同时出现在所要查询的区间中,我们在上一步多减了1.所以要把它加回来//处理单边界的情况可以将区间分成[L[i],i] 和 [i,R[i]].对于每个询问//进行离线处理.用树状数组求值.将区间按照右边界升序排列,对于区间查询//转换成f(r) - f(s - 1)的形式////感悟:////这道题,是我遇到的第一个区间覆盖的题目,哎,还是太弱了,什么都不会.//刚开始还理解了半天呢.不过现在看来还是挺好理解的.继续加油吧~~~FIGHTING!!!#include <cstring>#include <algorithm>#include <iostream>#include <cstdio>#include <cmath>#include <string>#include <vector>#include <queue>#define For(x,a,b,c) for (int x = a; x <= b; x += c)#define Ffor(x,a,b,c) for (int x = a; x >= b; x -= c)#define cls(x,a) memset(x,a,sizeof(x))using namespace std;typedef long long ll;const double PI = acos(-1.0);const double EPS = 1e-10;const int MAX_N = 2e5 + 8;const double INF = 1e9;int N,M;int a[MAX_N];bool isp[MAX_N];int pri[MAX_N];int L[MAX_N];int R[MAX_N];int cnt ;int MX;int pos[MAX_N];vector<int> g[MAX_N];struct ques{int l;int r;int id;ques(){}ques(int l,int r,int id):l(l),r(r),id(id){}bool operator < (const ques& o) const{return r < o.r;}}q[MAX_N],line[3][MAX_N];struct BIT{int sum[MAX_N];void init(){cls(sum,0);}int lowbit(int x){return x & -x;}void add(int x,int d){if (x == 0 || x == N + 1)return ;while(x <= N){sum[x] += d;x += lowbit(x);}}int query(int x){int res = 0 ;while(x >= 1){res += sum[x];x -= lowbit(x);}return res;}}bit;void init(){cnt = 0;isp[0] = isp[1] = 1;for (int i = 2 ;i < MAX_N;i ++){if (!isp[i]){pri[cnt++] = i;for (ll j = (ll)i * i ; j < MAX_N; j +=i)isp[j] = 1;}}}void get(){cls(pos,0);for (int i = 1 ;i <= N; i++){int p = 0;for (int j = 0 ; j < g[i].size();j ++){p = max(p,pos[g[i][j]]);pos[g[i][j]] = i;}L[i] = p;}for (int i = 1;i <= MX; i ++)pos[i] = N + 1;for (int i = N; i >= 1;i --){int p = N + 1;for (int j = 0; j < g[i].size();j ++){p = min(p,pos[g[i][j]]);pos[g[i][j]] = i;}R[i] = p;}}int ans[3][MAX_N];void getans(int id){sort(line[id] + 1, line[id] + N + 1);bit.init();int j = 1;for (int i = 1;i <= M; i++){int l = q[i].l;int r = q[i].r;int idx = q[i].id;while(j <= N && line[id][j].r <= r){bit.add(line[id][j].l,1);j++;}ans[id][idx] = bit.query(r) - bit.query(l - 1);}}int sum[MAX_N];void print(){for (int i = 1;i <= N;i ++){printf("%d %d\n",L[i],R[i]);}}void getPos(){for (int i  = 1;i <= MX;i ++)pos[i] = 0;for (int i = 1 ;i <= N;i ++){int tmp = a[i];int p = 0;for (int j = 2;j * j <= tmp ; j++){if (tmp % j)continue;p = max(p,pos[j]);pos[j] = i;while(tmp % j == 0)tmp /= j;}if (tmp > 1){p = max(p,pos[tmp]);pos[tmp] = i;}L[i] = p;}for (int i = MX ;i >=0 ; i--){pos[i] = N + 1;}for (int i = N ; i >= 1 ; i --){int tmp = a[i];int p = N + 1;for (int j = 2;j * j <= tmp ; j++){if (tmp % j)continue;p = min(p,pos[j]);pos[j] = i;while(tmp%j == 0) tmp /= j;}if (tmp > 1){p = min(p,pos[tmp]);pos[tmp] = i;}R[i] = p;}}void print1(){for (int i = 1;i <= N;i ++){for (int j = 0 ;j < g[i].size();j ++)printf("%d ",g[i][j]);puts("");}}void input(){MX = 0;for (int i = 1; i<= N;i ++){scanf("%d",&a[i]);MX = max(MX,a[i]);}for (int i = 1; i <= N;i ++)g[i].clear();for (int i = 1;i <= N;i ++){ // 这种求法MLEg[i].resize(7);int x = a[i];int c = 0;for (int j = 0 ; j < cnt && pri[x] ;j ++){if (x % pri[j] == 0){g[i][c++] = pri[j];while(x % pri[j] == 0){x /= pri[j];}}}if (x > 1)g[i][c++] = x;g[i].resize(c);}//print1();//get();getPos();//print();for (int i = 1;i <= M; i ++){int u,v;scanf("%d%d",&u,&v);q[i] = ques(u,v,i);sum[i] = v - u + 1;}sort(q+1,q+M+1);for (int i = 1;i <= N; i++){line[0][i] = ques(L[i],i,0);line[1][i] = ques(i,R[i],0);line[2][i] = ques(L[i],R[i],0);}getans(0);getans(1);getans(2);for (int i = 1;i <= M ;i ++){printf("%d\n",sum[i] - ans[0][i] - ans[1][i] + ans[2][i]);}}int main(){init();//freopen("1.in","r",stdin);while(scanf("%d%d",&N,&M)!=EOF){input();}return 0;}

0 0
原创粉丝点击