BZOJ3236:[AHOI2013]作业——题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3236:[AHOI2013]作业——题解相关的知识,希望对你有一定的参考价值。

https://www.lydsy.com/JudgeOnline/problem.php?id=3236 

第一种做法:

建两棵主席树分别处理两个问题。

第一个问题水,第二个问题参考SPOJ3267/DQUERY:D-query

但是代码量巨大,显然不能写。

第二种做法:

参考:https://blog.csdn.net/clover_hxy/article/details/56288794

对询问离线莫队,然后莫队里面套值域分块。

……值域分块还是很好写的就不讲了。

可以看出代码量巨短。

(emmm果然数据结构学傻了想的第一种做法敲了十分钟果断弃了查题解。)

(莫队还是太菜了要多练。)

#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e5+5;
const int M=1e6+5;
inline int read(){
    int x=0,w=1;char ch=0;
    while(ch<\'0\'||ch>\'9\'){if(ch==\'-\')w=-1;ch=getchar();}
    while(ch>=\'0\'&&ch<=\'9\'){x=(x<<1)+(x<<3)+ch-\'0\';ch=getchar();}
    return x*w;
}
struct data{
    int pos,l,r,a,b;
}q[M];
int a[N],cnt[N],ans[M][2],v[N],num[N],s,n,m;
inline int bel(int x){return (x-1)/s+1;}
inline bool cmp(data a,data b){
    return bel(a.l)==bel(b.l)?a.r<b.r:a.l<b.l;
}
inline void add(int k){
    if(!cnt[k])v[bel(k)]++;
    cnt[k]++;num[bel(k)]++;
}
inline void del(int k){
    cnt[k]--;num[bel(k)]--;
    if(!cnt[k])v[bel(k)]--;
}
void query(int pos,int l,int r){
    if(bel(l)==bel(r)){
    for(int i=l;i<=r;i++){
        if(cnt[i])ans[pos][1]++,ans[pos][0]+=cnt[i];
    }
    return;
    }
    for(int i=l;i<=bel(l)*s;i++)
    if(cnt[i])ans[pos][1]++,ans[pos][0]+=cnt[i];
    for(int i=(bel(r)-1)*s+1;i<=r;i++)
    if(cnt[i])ans[pos][1]++,ans[pos][0]+=cnt[i];
    for(int i=bel(l)+1;i<=bel(r)-1;i++)
    ans[pos][1]+=v[i],ans[pos][0]+=num[i];
}
int main(){
    n=read(),m=read();
    s=sqrt(n);
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++){
    q[i].pos=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 ql=1,qr=0;
    for(int i=1;i<=m;i++){
    while(ql<q[i].l)del(a[ql++]);
    while(ql>q[i].l)add(a[--ql]);
    while(qr<q[i].r)add(a[++qr]);
    while(qr>q[i].r)del(a[qr--]);
    query(q[i].pos,q[i].a,q[i].b);
    }
    for(int i=1;i<=m;i++){
    printf("%d %d\\n",ans[i][0],ans[i][1]);
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

以上是关于BZOJ3236:[AHOI2013]作业——题解的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3236: [Ahoi2013]作业

bzoj 3236: [Ahoi2013]作业(缺线段树)

AC日记——[Ahoi2013]作业 bzoj 3236

BZOJ3236: [Ahoi2013]作业 树状数组维护 莫队

bzoj3238 [Ahoi2013]差异 后缀数组+单调栈

●BZOJ 3238 [Ahoi2013]差异

(c)2006-2024 SYSTEM All Rights Reserved IT常识