zoukankan      html  css  js  c++  java
  • HDU4777 Rabbit Kingdom

     
    这道题题目挺容易看懂的,其实难度也不是很大,但是我竟然用了一个晚上+半个上午做这道题。
    首先,我们可以预处理出对于每个数,他左边第一个与他不互质的数的位置和他右边第一个与他不互质的数的位置。
    处理方法:
    我们先线筛,在线筛的同时记录筛每个数的那个质因子(from)。
    然后我们按照编号从小到达处理每一个数,用f[i]记录当前是i的倍数的最靠右的数的编号。
    我们每用from找到一个质因子,就把f[i]和当前的数的编号pos之间的关系处理好。
    具体代码:

    int f[maxn];
    void get_p(int x,int pos) {
      if(x==1) return ;
      int y;
      do {
        y=from[x];
        node[pos].x[1]=max(node[pos].x[1],f[y]);//更新pos左边第一个与他不互质的数
        node[f[y]].x[2]=min(node[f[y]].x[2],pos);//更新f[y]右边第一个与他不互质的数
        f[y]=pos;while(x%y==0) x/=y;
      }while(x!=1);
    }

    然后就是怎么利用这些东西的问题了。
    我们用x[0]表示数的编号(位置),x[1]表示左边第一个与他不互质的数的位置,x[2]表示右边第一个与他不互质的数的位置。
    这是一个三维的问题。我们需要找到满足$l leq x_0 leq r$且$ x_1 < l $且$ x_2 > r $的数的个数。
    因为$ x_1<x_0<x_2 $,所以我们可以降维。
    怎么降维呢?准确来说就是按照容斥列式子:
       $ [ x_1 < l land l leq x_0 leq r land x_2 > r ] $
    $ = [ l leq x_0 leq r ] \ - [ l leq x_0 leq r land x_1 geq l ] \ - [ l leq x_0 leq r land x_2 leq r ] \ + [ l leq x_0 leq r land x_1 geq l land x_2 leq r ] $
    $ = [ l leq x_0 leq r ] \ - ( [ x_0 leq r land x_1 geq l ] - [ x_0 < l land x_1 geq l ] ) \ - ( [ l leq x_0 land x_2 leq r ] - [ x_0 > r land x_2 leq r ] ) \ + [ x_1 geq l land x_2 leq r ] $
    $ = [ l leq x_0 leq r ] \ - [ x_0 leq r land x_1 geq l ] \ - [ l leq x_0 land x_2 leq r ] \ + [ x_1 geq l land x_2 leq r ] $
    然后直接用树状数组算这3个东西就可以了。
    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=2e5+10;
    int n,m,ans[maxn];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    struct Node{
    	int x[3];
    }node[maxn];
    bool cmp1(const Node& a,const Node& b) {
    	return a.x[2]<b.x[2];
    }
    struct Ask {
    	int x[3];
    }ask[maxn];
    bool cmp2(const Ask& a,const Ask& b) {
    	return a.x[2]<b.x[2];
    }
    
    int prime[maxn/5],totp,from[maxn];
    bool ok[maxn];
    void get_prime() {
    	for(int i=2;i<=maxn-5;++i) {
    		if(!ok[i]) prime[++totp]=i,from[i]=i;
    		for(int j=1;j<=totp&&prime[j]<=(maxn-5)/i;++j) {
    			ok[i*prime[j]]=1;from[i*prime[j]]=prime[j];
    			if(i%prime[j]==0) break;
    		}
    	}
    }
    
    int f[maxn];
    void get_p(int x,int pos) {
    	if(x==1) return ;
    	int y;
    	do {
    		y=from[x];
    		node[pos].x[1]=max(node[pos].x[1],f[y]);
    		node[f[y]].x[2]=min(node[f[y]].x[2],pos);
    		f[y]=pos;while(x%y==0) x/=y;
    	}while(x!=1);
    }
    
    int sz[maxn];
    void add(int pos) {while(pos<=n+1) sz[pos]++,pos+=(pos&-pos);}
    int q(int pos) {int rs=0; while(pos) rs+=sz[pos],pos-=(pos&-pos); return rs;}
    
    int main() {
    	n=read();m=read();
    	get_prime();int x,pos;
    	while(n||m) {
    		memset(f,0,sizeof(f));
    		for(int i=1;i<=n;++i) {
    			node[i].x[1]=0;node[i].x[2]=n+1;node[i].x[0]=i;
    			x=read(); get_p(x,i);
    		}
    		for(int i=1;i<=m;++i) {
    			ask[i].x[1]=read();ask[i].x[2]=read();
    			ask[i].x[0]=i;ans[i]=ask[i].x[2]-ask[i].x[1]+1;
    		}
    		sort(ask+1,ask+m+1,cmp2);
    		memset(sz,0,sizeof(sz));pos=1;
    		for(int i=1;i<=m;++i) {
    			x=ask[i].x[0];
    			while(pos<=n&&node[pos].x[0]<=ask[i].x[2]) add(node[pos].x[1]+1),pos++;
    			ans[x]-=(pos-1-q(ask[i].x[1]));
    		}
    		sort(node+1,node+n+1,cmp1);
    		memset(sz,0,sizeof(sz));pos=1;
    		for(int i=1;i<=m;++i) {
    			x=ask[i].x[0];
    			while(pos<=n&&node[pos].x[2]<=ask[i].x[2]) add(node[pos].x[0]+1),pos++;
    			ans[x]-=(pos-1-q(ask[i].x[1]));
    		}
    		memset(sz,0,sizeof(sz));pos=1;
    		for(int i=1;i<=m;++i) {
    			x=ask[i].x[0];
    			while(pos<=n&&node[pos].x[2]<=ask[i].x[2]) add(node[pos].x[1]+1),pos++;
    			ans[x]+=(pos-1-q(ask[i].x[1]));
    		}
    		for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    		
    		n=read();m=read();
    	}
    	return 0;
    }
    

      

     
    弱者就是会被欺负呀
  • 相关阅读:
    Delphi 窗体失踪在最上面的代码
    Delphi 目前使用delay函数功能
    Delphi Delay 延时计数的功能。 下面的方法都是思路,但是没有用在项目上
    Delphi 通过SQLite3, SQLiteTable3 操作数据库
    解决sqlite删除数据后,文件大小不变问题 转载
    delphi执行cmd命令和bat文件
    Delphi 获取sqlite中所有的表名
    delphi 获取USB口拔出和插入的状态
    深度揭密轮播插件核心代码的实现过程
    flowJS源码个人分析
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7649290.html
Copyright © 2011-2022 走看看