\(\\\)php
給出一個長爲 \(n\) 的數列 \(A\) 和 \(k\),屢次詢問:ios
對於一個區間 \([L_i,R_i]\),問區間內有多少個數在 \([a_i,b_i]\) 內,以及這些數共有多少個不一樣的值。c++
\(\\\)數組
看到最後一行心都涼了......優化
真的佩服鬆鬆鬆的速度 不知道比我高到哪裏去了spa
卡常卡到想吐(見代碼部分吧)`code
\(\\\)blog
首先確定莫隊,而後考慮第一問。排序
直接離散化以後權值樹狀數組,每次新加進來一個就在對應權值處 \(+1\) ,刪除 \(-1\) 。
對於第二問,咱們沒法肯定當前區間裏有多少個是個問題。
因而直接再開一個輔助桶,以及另外一個詢問用的權值樹狀數組。
加入時若之前沒有(桶爲空),則在這一權值處 \(+1\) ,刪除時若桶清空成 \(0\) ,則在對應權值處 \(-1\) 。
回答就直接區間減法便可。
注意 lower_bound
和upper_bound
的時候可能越界,因此要加上哨兵。
\(\\\)
仍是說一下卡經常使用了點啥吧.....
BZOJ 專用的 int 優化
讀入 & 輸出優化
莫隊對詢問排序時的奇偶性討論
很迷的塊的大小,實測 \(\frac{N}{\sqrt M}\) 最快
關於這個粘一個洛穀日報上的證實
咱們設塊長度爲 \(S\) ,那麼對於任意多個在同一塊內的詢問,挪動的距離就是 \(n\),一共\(\frac{n}{S}\) 個塊,移動的總次數就是\(\frac{n^2}{S}\),移動可能跨越塊,因此還要加上一個 \(mS\) 的複雜度,總複雜度爲 \(O(\frac{n^2}{S}+mS)\) ,咱們要讓這個值儘可能小,\(S\) 取 \(\frac{n}{\sqrt{m}}\) 是最優的,此時複雜度爲
\[ O(\frac{n^2}{\frac{n}{\sqrt{m}}}+m(\frac{n}{\sqrt{m}}))=O(n\sqrt{m}) \]
#include<cmath> #include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 100010 #define M 1000010 #define Rg register #define gc getchar using namespace std; inline int rd(){ int x=0; bool f=0; char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();} return f?-x:x; } inline void print(int x){ Rg int y=10,len=1; while(x>=y){y=(y<<1)+(y<<3);++len;} while(len--){y/=10;putchar('0'+x/y);x%=y;} } int n,m,tot,ans,ans1[M],ans2[M],s[N],bl[N],cnt[N],tmp[N]; struct Q{int l,r,L,R,id;}q[M]; inline bool cmp(Q x,Q y){ if(bl[x.l]!=bl[y.l]) return bl[x.l]<bl[y.l]; return bl[x.l]&1?x.r<y.r:x.r<y.r; } struct BIT{ int c[N]; inline int lowbit(int x){return x&-x;} inline void add(int p,int x){ for(;p<=n;p+=lowbit(p)) c[p]+=x; } inline int query(int p){ int res=0; for(;p;p-=lowbit(p)) res+=c[p]; return res; } }bitcnt,bitsum; inline void add(int p){ ++cnt[s[p]]; bitsum.add(s[p],1); if(cnt[s[p]]==1) bitcnt.add(s[p],1); } inline void del(int p){ --cnt[s[p]]; bitsum.add(s[p],-1); if(!cnt[s[p]]) bitcnt.add(s[p],-1); } int main(){ n=rd(); m=rd(); int t=n/sqrt(m); for(Rg int i=1;i<=n;++i){ tmp[i]=s[i]=rd(); bl[i]=i/t+1; } sort(tmp+1,tmp+1+n); for(Rg int i=1;i<=n;++i){ tmp[++tot]=tmp[i]; while(tmp[i+1]==tmp[i]) ++i; } tmp[++tot]=2000000000; for(Rg int i=1;i<=n;++i) s[i]=lower_bound(tmp+1,tmp+1+tot,s[i])-tmp; for(Rg int i=1;i<=m;++i){ q[i].l=rd(); q[i].r=rd(); q[i].id=i; q[i].L=lower_bound(tmp+1,tmp+1+tot,rd())-tmp; q[i].R=upper_bound(tmp+1,tmp+1+tot,rd())-tmp-1; } sort(q+1,q+1+m,cmp); int l=1,r=1; cnt[s[1]]=1; bitcnt.add(s[1],1); bitsum.add(s[1],1); for(Rg int i=1;i<=m;++i){ if(q[i].L>q[i].R){ ans1[q[i].id]=ans2[q[i].id]=0; continue; } while(l<q[i].l){del(l);++l;} while(l>q[i].l){--l;add(l);} while(r>q[i].r){del(r);--r;} while(r<q[i].r){++r;add(r);} ans1[q[i].id]=bitsum.query(q[i].R)-bitsum.query(q[i].L-1); ans2[q[i].id]=bitcnt.query(q[i].R)-bitcnt.query(q[i].L-1); } for(Rg int i=1;i<=m;++i){ print(ans1[i]); putchar(' '); print(ans2[i]); putchar('\n'); } return 0; }