• 区间种类统计类问题


    1. 莫队算法

    将询问按照左端点分为sqrt级别块进行排序,然后顺序处理.

    例题 小Z的袜子

    2. 树状数组

    一种很有技巧性的东西

    对于一些离线的这类问题,我们可能要统计在一段区间内的种类数,那么我们可以用差分的办法维护前缀和.

    具体地说,我们将询问按左端点排序,那么我们就可以从左到右处理了.

    看代码比较清楚,好好想一想就懂了.

    SDOI HH的项链

    #include <cstdio>
    #include <algorithm>
    int a[60000],p[60000],bit[60000],n,m,i,j,k,c[2000000];
    #define lowbit(x) (x&(-x))
    inline int read(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    inline void add(int a){
    	for(;a<=n;a+=lowbit(a)) ++bit[a];
    }
    inline int qry(int a){
    	int res=0;
    	for(;a;a-=lowbit(a)){
    		res+=bit[a];
    	}
    	return res;
    }
    inline void cons(){
    	for(i=1;i<=n;++i){
    		bit[i]+=a[i];
    		bit[i+lowbit(i)]+=bit[i];
    	}
    }
    struct query{
    	int l,r,id;
    } qrs[300000];
    bool cmp(const query& a,const query& b){
    	return a.l<b.l;
    }
    int qrp;
    int ans[300000];
    char s[8000000],pp[15];
    int strl,strp;
    void record(int i){
        strp=0;
        while(i){
            j=i/10;
            pp[strp++]=i-j*10+'0';
            i=j;
        }
        while(~(--strp)){
            s[strl++]=pp[strp];
        }
        s[strl++]='
    ';
    }
    int main(){
    	n=read();
    	for(i=1;i<=n;++i){
    		j=read();
    		if(!c[j]) a[i]=1;
    		c[j]=p[c[j]]=i;
    	}
    	m=read();
    	for(i=0;i<m;++i) qrs[i].l=read(),qrs[i].r=read(),qrs[i].id=i;
    	std::sort(qrs,qrs+m,cmp);
    	cons();
    	qrp=0;
    	for(i=1;i<=n;++i){
    		if(qrs[qrp].l==i){
    			j=qry(i-1);
    			while(qrs[qrp].l==i&&qrp<m){
    				ans[qrs[qrp].id]=qry(qrs[qrp].r)-j;
    				++qrp;
    			}
    		}
    		if(p[i]) add(p[i]);
    	}
    	for(i=0;i<m;++i) record(ans[i]);
    	s[strl-1]='';
    	puts(s);
    	return 0;
    }
    

    read()函数是读入,record用来输出,add就是树状数组的update,qry就是树状数组的查询,cons从a中构造树状数组.

    #include <cstdio>
    #include <algorithm>
    int a[1000010],p[1000010],bit[1000010],n,m,i,j,k,c[1000010],q[1000010];
    #define lowbit(x) (x&(-x))
    inline int read(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    inline void add(int a,int p){
    	for(;a<=n;a+=lowbit(a)) bit[a]+=p;
    }
    inline int qry(int a){
    	int res=0;
    	for(;a;a-=lowbit(a)){
    		res+=bit[a];
    	}
    	return res;
    }
    inline void cons(){
    	for(i=1;i<=n;++i){
    		bit[i]+=a[i];
    		bit[i+lowbit(i)]+=bit[i];
    	}
    }
    struct query{
    	int l,r,id;
    } qrs[1000010];
    bool cmp(const query& a,const query& b){
    	return a.l<b.l;
    }
    int qrp;
    int ans[1000010];
    int main(){
    	n=read();
    	k=read();
    	m=read();
    	for(i=1;i<=n;++i) q[i]=read();
    	for(i=n;i;--i) p[i]=c[q[i]],c[q[i]]=i;
    	for(i=1;i<=k;++i) if(p[c[i]]) ++a[p[c[i]]];
    	for(i=0;i<m;++i) qrs[i].l=read(),qrs[i].r=read(),qrs[i].id=i;
    	std::sort(qrs,qrs+m,cmp);
    	cons();
    	qrp=0;
    	for(i=1;i<=n;++i){
    		if(qrs[qrp].l==i){
    			j=qry(i-1);
    			while(qrs[qrp].l==i&&qrp<m){
    				ans[qrs[qrp].id]=qry(qrs[qrp].r)-j;
    				++qrp;
    			}
    		}
    		if(p[i]) add(p[i],-1);
    		if(p[p[i]]) add(p[p[i]],1);
    	}
    	for(i=0;i<m;++i) printf("%d
    ",ans[i]);
    	return 0;
    }
  • 相关阅读:
    作用域面试题
    js··BOM 浏览器对象模型
    js···DOM2动态创建节点
    js ·节点的知识点
    js·逻辑运算
    js···元素的属性
    什么是函数封装。
    hive 历史拉链表的处理
    [转]实现Hive数据同步更新的shell脚本
    python 3 过滤股票
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4468345.html
Copyright © 2020-2023  润新知