• 【题解】[AHOI2013]作业


    Link

    题目大意:(n)个数,(m)个询问,每次四个参数,(l,r,a,b),问区间([l,r])中出现过的,数值在([a,b])区间中的数的个数以及区间([l,r])中数值在([a,b])中的数的个数。

    注意理解 这两个是不一样的。

    ( ext{Solution:})

    观察到区间颜色出现次数可以想到莫队。

    由于多了一个限制,那么我们考虑如何更新答案,并利用前缀思想:

    指针移动的时候,维护颜色数以及这个颜色的值,对应在一个树状数组上更新。注意维护两个树状数组,分别处理两个询问。其他的和普通莫队没什么区别。

    复杂度(O(nsqrt{n}log n).)此处替换(m)因为它们同阶。

    其实还有莫队套分块的更优复杂度以及(KDT,cdq)分治等多种做法,在此不做赘述。

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) (x&(-x))
    const int MAXN=1e6+10;
    int col[MAXN],cnt[MAXN],a[MAXN],n,m,tr[MAXN];
    int bl[MAXN],siz,bnum,now,tr1[MAXN];
    pair<int,int>ans[MAXN];
    inline bool R(char C){return C>='0'&&C<='9';}
    inline int read(){
    	int s=0;
    	char ch=getchar();
    	while(!R(ch))ch=getchar();
    	while(R(ch))s=s*10+ch-48,ch=getchar();
    	return s;
    }
    inline void write(int x){
    	if(x<0)putchar('-'),x=-x;
    	if(x>=10)write(x/10);
    	putchar(x%10+48);
    }
    struct Q{
    	int l,r,a,b,id;
    }q[MAXN];
    inline bool cmp(Q a,Q b){return (bl[a.l]^bl[b.l])?bl[a.l]<bl[b.l]:(bl[a.l]&1)?a.r<b.r:a.r>b.r;}
    inline void change(int x,int v){for(;x<=n;x+=lowbit(x))tr[x]+=v;}
    inline int sum(int x){int res=0;for(;x;x-=lowbit(x))res+=tr[x];return res;}
    inline void change2(int x,int v){for(;x<=n;x+=lowbit(x))tr1[x]+=v;}
    inline int sum2(int x){int res=0;for(;x;x-=lowbit(x))res+=tr1[x];return res;}
    
    inline void del(int x){
    	--cnt[a[x]];
    	if(!cnt[a[x]])now--,change(a[x],-1);
    	change2(a[x],-1);
    }
    inline void add(int x){
    	if(!cnt[a[x]])change(a[x],1),now++;
    	++cnt[a[x]];change2(a[x],1);
    }
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	siz=sqrt(n);bnum=ceil((double)n/siz);
    	for(int i=1;i<=bnum;++i)for(int j=(i-1)*siz+1;j<=i*siz;++j)bl[j]=i;
    	for(int i=1;i<=m;++i){
    		q[i].id=i;
    		q[i].l=read();
    		q[i].r=read();
    		q[i].a=read();
    		q[i].b=read();
    	}
    	sort(q+1,q+m+1,cmp);
    	int l=1,r=0;
    	for(int i=1;i<=m;++i){
    		int ql=q[i].l,qr=q[i].r;
    		while(l<ql)del(l++);
    		while(l>ql)add(--l);
    		while(r<qr)add(++r);
    		while(r>qr)del(r--);
    		ans[q[i].id].first=sum2(q[i].b)-sum2(q[i].a-1);
    		ans[q[i].id].second=sum(q[i].b)-sum(q[i].a-1);
    	}
    	for(int i=1;i<=m;++i)write(ans[i].first),putchar(' '),write(ans[i].second),putchar('
    ');
    	return 0;
    }
    
  • 相关阅读:
    4.文本规范化处理
    2.自动文本分类
    3.文本分类的蓝图
    1.什么是文本分类
    2.文本规范化
    Python 处理和理解文本
    1.文本切分
    验证码识别
    随机函数
    Java编程思想笔记(多态)
  • 原文地址:https://www.cnblogs.com/h-lka/p/12944679.html
Copyright © 2020-2023  润新知