【BZOJ3236】【AHOI2013】作业
莫队算法即可。
注意到修改有次,而询问只有次,考虑用一个询问,修改的权值分块来维护当前书的集合,总时间复杂度。
#include <cctype>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAXSIZE=40000020;int bufpos;char buf[MAXSIZE];void init(){buf[fread(buf,1,MAXSIZE,stdin)]='\0';bufpos=0;}int readint(){int val=0;for(;!isdigit(buf[bufpos]);bufpos++);for(;isdigit(buf[bufpos]);bufpos++)val=val*10+buf[bufpos]-'0';return val;}struct block{int n,sz,num;int sum[321],o[321];int cnt[100001];int w[100001];int st[321];void init(int n){sz=sqrt(n)+0.5;num=(n-1)/sz+1;st[1]=1;for(int i=1;i<=n;i++)w[i]=(i-1)/sz+1;for(int i=2;i<=num;i++)st[i]=st[i-1]+sz;st[num+1]=n+1;}void update(int x,int sgn){if (!cnt[x])o[w[x]]++;cnt[x]+=sgn;sum[w[x]]+=sgn;if (!cnt[x])o[w[x]]--;}pair<int,int> query(int a,int b){int res1=0,res2=0;if (w[a]==w[b]){for(int i=a;i<=b;i++)res1+=cnt[i],res2+=!!cnt[i];return make_pair(res1,res2);}for(int i=w[a]+1;i<w[b];i++)res1+=sum[i],res2+=o[i];for(int i=a;i<st[w[a]+1];i++)res1+=cnt[i],res2+=!!cnt[i];for(int i=st[w[b]];i<=b;i++)res1+=cnt[i],res2+=!!cnt[i];return make_pair(res1,res2);}}t;int sz;struct query{int p,l,r,a,b;bool operator <(const query& rhs)const{return l/sz!=rhs.l/sz?l/sz<rhs.l/sz:r<rhs.r;}}q[1000001];int a[100001];pair<int,int> ans[1000001];int main(){init();int n=readint(),m=readint();sz=sqrt(n)+0.5;for(int i=1;i<=n;i++)a[i]=readint();for(int i=1;i<=m;i++)q[i].p=i,q[i].l=readint(),q[i].r=readint(),q[i].a=readint(),q[i].b=readint();sort(q+1,q+m+1);int l=1,r=0;t.init(n);for(int i=1;i<=m;i++){while(l<q[i].l)t.update(a[l++],-1);while(r<q[i].r)t.update(a[++r],1);while(l>q[i].l)t.update(a[--l],1);while(r>q[i].r)t.update(a[r--],-1);ans[q[i].p]=t.query(q[i].a,q[i].b);}for(int i=1;i<=m;i++)printf("%d %d\n",ans[i].first,ans[i].second);}
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
本文链接:https://www.q234rty.top/2017/02/17/bzoj3236/
