【BZOJ】【P3236】【Ahoi2013】【作业】【题解】【莫队】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3236

一把辛酸泪

【BZOJ】【P3236】【Ahoi2013】【作业】【题解】【莫队】_第1张图片

看完题面就想到莫队了

又看见了底下一行小字:

By wangyisong1996加强数据

wangyisong神犇加强的数据估计莫队就过不了吧……

纠结了好久最终决定还是写莫队

然后就是WA+RE+TLE

就当我认定莫队必挂的时候看到了ydc神犇的莫队题解

交上去……90sA了

卧槽继续搞我的常数!!!

常数日志:

使用fread读入

使用puts输出

预处理pos

加上inline

交——RE

使用getchar读入

使用printf输出

不预处理pos

继续使用inline

交——RE

关闭inline

预处理pos

交——TLE

使用inline

把树状数组从类改成两个函数

交——TLE

对着ydc神犇的标程改改改改

交——TLE

都一样了怎么还T……

然后发现了一句话

    inline bool operator<(const qes oth)const{
        return pos[l]<pos[oth.l]||(pos[l]==pos[oth.l]/sqrtn&&r<oth.r);
    }

真想一头撞死

改,交——RE

RE了!??!?!?!?!

又发现了一句话

const int maxn=1e5+5;
int ans1[maxn],ans2[maxn];

一头撞死++

我再交——

终于A了55555555

Code:

#include<bits/stdc++.h>
#define lowbit(x) (x&-x)
using namespace std;
const int maxn=1e5+5;
int n,m,sqrtn,a[maxn];
int vis[maxn],pos[maxn],ans1[maxn*10],ans2[maxn*10];
int d1[maxn],d2[maxn];
void read(int &res){
    res=0;char c=getchar();for(;!isdigit(c);c=getchar());
    for(;isdigit(c);res=res*10+c-'0',c=getchar());
}
inline int get1(int x){int o=0;while(x)o+=d1[x],x-=lowbit(x);return o;};
inline void updata1(int x,int f){while(x<=n)d1[x]+=f,x+=lowbit(x);}
inline int get2(int x){int o=0;while(x)o+=d2[x],x-=lowbit(x);return o;};
inline void updata2(int x,int f){while(x<=n)d2[x]+=f,x+=lowbit(x);}
struct qes{
    int l,r,a,b,id;
    inline bool operator<(const qes oth)const{
        return pos[l]<pos[oth.l]||(pos[l]==pos[oth.l]&&r<oth.r);
    }
}q[maxn*10];
int main(){
    read(n);read(m);
    sqrtn=sqrt(n);
    for(int i=1;i<=n;++i)read(a[i]);
    for(int i=1;i<=n;++i)pos[i]=i/sqrtn;
    for(int i=1;i<=m;i++){
        read(q[i].l);read(q[i].r);
        read(q[i].a);read(q[i].b);q[i].id=i;
    }sort(q+1,q+1+m);
    int L=1,R=1;
    updata1(a[1],1);
    updata2(a[1],1);
    vis[a[1]]++;
    for(int i=1;i<=m;i++){
        while(L>q[i].l){
            L--;
            updata1(a[L],1);
            if(!vis[a[L]])updata2(a[L],1);
            vis[a[L]]++;
        }               
        while(R<q[i].r){
            R++;
            updata1(a[R],1);
            if(!vis[a[R]])updata2(a[R],1);
            vis[a[R]]++;        
        }   
        while(L<q[i].l){
            updata1(a[L],-1);
            if(!--vis[a[L]])updata2(a[L],-1);
            L++;
        }       
        while(R>q[i].r){
            updata1(a[R],-1);
            if(!--vis[a[R]])updata2(a[R],-1);
            R--;        
        }           
        ans1[q[i].id]=get1(q[i].b)-get1(q[i].a-1);
        ans2[q[i].id]=get2(q[i].b)-get2(q[i].a-1);
    }
    for(int i=1;i<=m;i++)
    printf("%d %d\n",ans1[i],ans2[i]);
}


你可能感兴趣的:(bzoj)