P4688 [Ynoi2016]掉进兔子洞
//Pro:P4688 [Ynoi2016]掉进兔子洞 //ans= r1-l1+1 + r2-l2+1 +r3-l3+1 - ∑min(cnt1[i],cnt2[i],cnt3[i])*3 //计算cnt可以用莫队 //如何计算cnt的min //用bitset (第一次用这玩意真神奇 //将原数组排个序 //将每个数离散化为它在有序数组中出现的第一个位置 //bitset里的每一位对应有序后的原数组的每一位 //那么对于一个询问,三个bitset的&就是∑min(cnt1[i],cnt2[i],cnt3[i]) #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<bitset> using namespace std; typedef long long LL; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } const int N=100000; const int T=25000; int n,m,bound; int a[N+5],b[N+5]; int belong[N+5]; struct LINE { int l,r,id; bool operator < (const LINE &A) const { return belong[l]==belong[A.l]?r<A.r:l<A.l; } }line[T*3+5]; bitset<N> F[T+5],f; int ans[T+5],cnt[N+5]; bool mark[T+5]; inline void update(int pos,bool flag) { int x=a[pos]; if(flag) ++cnt[x],f[x+cnt[x]-2]=1; else f[x+cnt[x]-2]=0,--cnt[x]; } inline void solve(int t) { bound=0; memset(mark,0,sizeof(mark)); memset(ans,0,sizeof(ans)); for(int i=1;i<=t;++i) { for(int j=0;j<3;++j) { line[++bound].l=read(), line[bound].r=read(), line[bound].id=i; ans[i]+=line[bound].r-line[bound].l+1; } } sort(line+1,line+bound+1); f.reset(); memset(cnt,0,sizeof(cnt)); int L=1,R=0; for(int i=1;i<=bound;++i) { for(;R<line[i].r;update(++R,1)); for(;L>line[i].l;update(--L,1)); for(;R>line[i].r;update(R--,0)); for(;L<line[i].l;update(L++,0)); if(!mark[line[i].id]) F[line[i].id]=f,mark[line[i].id]=1; else F[line[i].id]&=f; } for(int i=1;i<=t;++i) { ans[i]-=F[i].count()*3; cout<<ans[i]<<'\n'; } } int S; int main() { n=read(),m=read(); S=sqrt(n); for(int i=1;i<=n;++i) { b[i]=read(),a[i]=b[i]; belong[i]=(i-1)/S+1; } sort(b+1,b+n+1); for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+n+1,a[i])-b; while(m) { if(m<=T) solve(m),m=0; else solve(T),m-=T; } return 0; }