题解:AT_abc389_f [ABC389F] Rated Range

· · 题解

解题方法

一道分块板子。

我们可以看到数值的范围很小,所以考虑分块。

$a$ 数组代表小块,也就是 $a[x]$ 代表数值 $x$ 无法在大块中体现的部分。 可能有点绕,大家可结合代码理解。 说完数组定义后讲一下方法。 对于每一对 $l$ 和 $r$,我们二分把其可以影响到的数值上限和下限求出来,对应把这段范围在块上面加其贡献,也就是 $+1$。 ## Code ```cpp #include<bits/stdc++.h> #define int long long #define qk(x) ((x-1)/B+1) //qk(x) 求出数值x在哪一个块当中 using namespace std; const int N=6e5,B=sqrt(N)+1,MAXN=1e7+10; //N 数值范围,B 块的个数与大小 int n,m,p,q,len,len1,a[MAXN],b[MAXN]; //a[x]+b[qk(x)] 就是当前x经过前面评分变化后的值 int ef(int x){ //二分求上限下限 if(a[N]+b[qk(N)]<x) return N+1; int l=1,r=N; while(l<r){ int mid=(l+r)/2; if(a[mid]+b[qk(mid)]<x) l=mid+1; else r=mid; } return l; } signed main(){ cin>>n; for(int i=1;i<=N;i++) a[i]=i; for(int i=1;i<=n;i++) { int l,r; cin>>l>>r; int l1=ef(l),r1=ef(r+1)-1,kl=qk(l1),kr=qk(r1); if(kl==kr) for(int i=l1;i<=r1;i++) a[i]++;//在同一块中,小块直接加。 else{ //若上限下限不在同一块中 for(int i=l1;i<=kl*B;i++) a[i]++;//把前面多出来的算上 for(int i=kr*B-B+1;i<=r1;i++) a[i]++;//后面多的也算上 for(int i=kl+1;i<=kr-1;i++) b[i]++;//中间整块整块的,直接大块中加 //如果看不懂这里,建议复习一下分块模板 } } cin>>m; for(int i=1,x;i<=m;i++){ cin>>x; cout<<a[x]+b[qk(x)]<<endl;//单独贡献+同块贡献 } return 0; } ``` ### 完结散花