让 f x f_x fx 表示初始 Rated 为 x x x 参加完所有比赛能涨多少分。
证明 { x + f x } \{x+f_x\} {x+fx} 有单调性:
设 y ≤ x y\le x y≤x
对于一场比赛 [ L , R ] [L,R] [L,R],有如下情况:
- L ≤ y ≤ R < x L\le y\le R<x L≤y≤R<x,参加完后仍然满足 y + 1 ≤ x y+1\le x y+1≤x
- L ≤ y ≤ x ≤ R L\le y \le x\le R L≤y≤x≤R,参加完后仍然满足 y + 1 ≤ x + 1 y+1\le x+1 y+1≤x+1
- y ≤ x ≤ L y \le x\le L y≤x≤L,参加完后仍然满足 y ≤ x y\le x y≤x
所以 { x + f x } \{x+f_x\} {x+fx} 具有单调性。
因此可以二分比赛 [ L , R ] [L,R] [L,R],原始 Rated ∈ [ l , r ] \in[l,r] ∈[l,r] 能涨分。
用树状数组维护即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[500005];
void add(int d,int x){
while(d<=500000){
a[d]+=x;
d+=d&-d;
}
}
int get(int d){
int sum=0;
while(d){
sum+=a[d];
d-=d&-d;
}
return sum;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
int l,r;
cin>>l>>r;
int L=1,R=500000;
while(L<=R){
int mid=(L+R)>>1;
if(get(mid)+mid>=l)R=mid-1;
else L=mid+1;
}
l=R+1;
L=1,R=500000;
while(L<=R){
int mid=(L+R)>>1;
if(get(mid)+mid<=r)L=mid+1;
else R=mid-1;
}
r=L-1;
if(r<l)continue;
add(l,1);
add(r+1,-1);
}
cin>>m;
while(m--){
int x;
cin>>x;
cout<<x+get(x)<<"\n";
}
return 0;
}