牛客 - Alice and Bob(尺取+二分)
題目鏈接:點擊查看
題目大意:給出一個長度為 nnn 的數列,和一個數字 kkk。現在給出 mmm 次詢問,每次查詢需要回答區(qū)間 [l,r][l,r][l,r] 內有多少個子區(qū)間,滿足區(qū)間內不同的數字個數大于等于 kkk
題目分析:一開始看到強制在線和區(qū)間問題以為是主席樹,后來發(fā)現 kkk 自始至終都是不變的。這樣每個點作為左端點時,假設某個點可以作為右端點 rrr 與其對應,那么顯然當 i∈[r+1,n]i\in[r+1,n]i∈[r+1,n] 的 iii 作為右端點時,區(qū)間 [l,i][l,i][l,i] 同樣也是滿足條件的
所以我們只需要預處理出對于每個點作為左端點 lll 時,可以匹配的下標最小的右端點 rrr 即可,這里我記為 bib_ibi?,數組 bbb 不難看出可以直接用尺取來求,這里不多贅述了
那么考慮對于每次詢問 [l,r][l,r][l,r] ,答案顯然就是 ∑i=lrmax(0,r?bi+1)\sum_{i=l}^{r}max(0,r-b_i+1)∑i=lr?max(0,r?bi?+1)
然后就需要發(fā)現數組 bbb 的一個小性質,那就是數組 bbb 是單調不減的,所以對于上述求和公式就可以找到一個分界點 pospospos。有 i∈[l,pos]i\in[l,pos]i∈[l,pos] 時,滿足 r?bi+1>=0r-b_i+1>=0r?bi?+1>=0;同理 i∈[pos+1,r]i\in[pos+1,r]i∈[pos+1,r] 時,滿足 r?bi+1<0r-b_i+1<0r?bi?+1<0,這樣一來 [pos+1,r][pos+1,r][pos+1,r] 的貢獻就可以忽略不計了
到此為止只需要將上述求和公式拆一下就可以輕松實現了:
∑i=lrmax(0,r?bi+1)=∑i=lposbi+(r+1)?(pos?l+1)\sum_{i=l}^{r}max(0,r-b_i+1)=\sum_{i=l}^{pos}b_i+(r+1)*(pos-l+1)∑i=lr?max(0,r?bi?+1)=∑i=lpos?bi?+(r+1)?(pos?l+1)
代碼:
// Problem: Alice and Bob // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/17148/C // Memory Limit: 1048576 MB // Time Limit: 4000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; int a[N],b[N]; LL sum[N]; map<int,int>mp; LL get_sum(int l,int r) {return sum[r]-sum[l-1]; } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m,k;read(n),read(m),read(k);for(int i=1;i<=n;i++) {read(a[i]);}int r=0,cnt=0;for(int i=1;i<=n;i++) {while(cnt<k&&r<=n) {r++;mp[a[r]]++;if(mp[a[r]]==1) {cnt++;}}if(cnt>=k) {b[i]=r;} else {b[i]=n+1;}sum[i]=sum[i-1]+b[i];mp[a[i]]--;if(mp[a[i]]==0) {cnt--;}}LL ans=0;while(m--) {LL l,r;read(l),read(r);l=(l^ans)+1;r=(r^ans)+1;if(l>r) {swap(l,r);}int ll=l,rr=r,pos=-1;while(ll<=rr) {int mid=(ll+rr)>>1;if(0<=r-b[mid]+1) {pos=mid;ll=mid+1;} else {rr=mid-1;}}if(pos==-1) {puts("0");ans=0;} else {LL ans1=1LL*(r+1)*(pos-l+1);LL ans2=get_sum(l,pos);printf("%lld\n",ans=ans1-ans2);}}return 0; }總結
以上是生活随笔為你收集整理的牛客 - Alice and Bob(尺取+二分)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1523D L
- 下一篇: 牛客 - Dance with a st