zoukankan      html  css  js  c++  java
  • BZOJ 3236 AHOI 2013 作业 莫队+树状数组

    BZOJ 3236 AHOI 2013 作业

    内存限制:512 MiB 时间限制:10000 ms 标准输入输出
     
     
    题目类型:传统 评测方式:文本比较

    题目大意:

    此时己是凌晨两点,刚刚做了Codeforces的小A掏出了英语试卷。英语作业其实不算多,一个小时刚好可以做完。然后是一个小时可以做完的数学作业,接下来是分别都是一个小时可以做完的化学,物理,语文......小A压力巨大。woc他竟然一个小时搞完语文卷子

    这是小A碰见了一道非常恶心的数学题,给定了一个长度为n的数列和若干个询问,每个询问是关于数列的区间表示数列的第l个数到第r个数),首先你要统计该区间内大于等于a,小于等于b的数的个数,其次是所有大于等于a,小于等于b的,且在该区间中出现过的数值的个数。

    小A望着那数万的数据规模几乎绝望,只能向大神您求救,请您帮帮他吧。

    这么说其实不太清楚,说白了就是一个是可以记录重复的而一个不能

    输入格式

    第一行n,m

    接下来n个数表示数列

    接下来m行,每行四个数l,r,a,b

    输出格式

    输出m行,分别对应每个询问,输出两个数,分别为在l到r这段区间中大小在[a,b]中的数的个数,以及大于等于a,小于等于b的,且在该区间中出现过的数值的个数(具体可以参考样例)。

    样例

    样例输入

    3 4
    1 2 2
    1 2 1 3
    1 2 1 1
    1 3 1 3
    2 3 2 3

    样例输出

    2 2
    1 1
    3 2
    2 1

    数据范围与提示

    N=100000,M=1000000

    题解:

    我们采用莫队的算法,将询问的区间排序

    维护两个权值树状数组,一个是可以重复的树状数组A,一个是不能重复的树状数组B,

    我们在删除操作时,对于那个可以有重复的树状数组A,我们无条件删除它

    而那个不能重复的树状数组B,我们需要判断能否删去

    开一个数组,cnt[i]表示权值i出现的次数

    如果我们在删除一个i后cnt[i]变成了0,说明现在区间中没有权值i出现,那么我们就可以删去它

    对于加的操作,其实是一样的,对于树状数组A,我们无条件加上它

    对于树状数组B,如果当前cnt[i]==0,那么说明i是一个新出现的值,需要在树状数组B中加入i

    最后一遍询问[a,b]就可得出答案

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<cmath>
    #define MAXN 100005
    #define MAXM 1000005
    #define ll long long
    #define re register
    using namespace std;
    ll n,m,a[MAXN],block[MAXM],blo,l=1,r=0,ans1[MAXM],ans2[MAXM],cnt[MAXN];
    struct node{
    	ll l,r,a,b,id;
    	friend inline bool operator < (node a,node b){
    		return block[a.l]==block[b.l]?a.r<b.r:a.l<b.l;
    	}
    }ask[MAXM];
    struct BIT{
    	ll c[MAXN];
    	ll lowbit(re ll x){return x&(-x);}
    	inline void update(re ll pos,re ll data){
    		while(pos<=n){
    			c[pos]+=data;
    			pos+=lowbit(pos);
    		}
    	}
    	inline ll query(re ll pos){
    		re ll sum=0;
    		while(pos>0){
    			sum+=c[pos];
    			pos-=lowbit(pos);
    		}
    		return sum;
    	}
    }tree1,tree2;
    inline void add(re ll x){
    	if(x==0) return ;
    	tree1.update(x,1);
    	if(cnt[x]==0) tree2.update(x,1);
    	cnt[x]++;
    }
    inline void del(re ll x){
    	if(x==0) return ;
    	tree1.update(x,-1);
    	cnt[x]--;
    	if(cnt[x]==0) tree2.update(x,-1);
    }
    signed main(){
    	scanf("%lld%lld",&n,&m);
    	blo=(ll)sqrt(n);
    	for(re ll i=1;i<=n;i++)
    		scanf("%lld",&a[i]);
    	for(re ll i=1;i<=m;i++){
    		scanf("%lld%lld%lld%lld",&ask[i].l,&ask[i].r,&ask[i].a,&ask[i].b);
    		ask[i].id=i;
    		block[i]=i/blo+1;
    	}
    	sort(ask+1,ask+m+1);
    	for(re ll i=1;i<=m;i++){
    		while(l<ask[i].l) del(a[l++]);
    		while(l>ask[i].l) add(a[--l]);
    		while(r>ask[i].r) del(a[r--]);
    		while(r<ask[i].r) add(a[++r]);
    		ans1[ask[i].id]=tree1.query(ask[i].b)-tree1.query(ask[i].a-1);
    		ans2[ask[i].id]=tree2.query(ask[i].b)-tree2.query(ask[i].a-1);
    	}
    	for(re ll i=1;i<=m;i++)
    		printf("%lld %lld
    ",ans1[i],ans2[i]);
    	return 0;
    }
    
  • 相关阅读:
    swift
    swift
    ios
    Swift
    swift
    swift
    /var/log/cron
    Django 数据传递
    HTML 属性
    HTML 元素
  • 原文地址:https://www.cnblogs.com/Juve/p/11255827.html
Copyright © 2011-2022 走看看