题解——[ABC282F] Union of Two Sets
前言
在这里提供运用 ST 表思想但又略不同于 ST 表的构造方法,能够在
解析
构造的思路是这样的:
设
当
当
当
当
事实上,如果我们构造了一连串的一个长度为
具体地,对于满足
这样,我们就只需要从长度为
通过这种方法构造出来的区间,第
由此可见,当
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 4e3 + 5;
vector<int> v[N];//v[i][j]表示是否构造出长度第 i 短,左端点位于 j 的区间,
int s[N],lth[N];//s[i]表示构造出来的第 1 至第 i 短的区间个数
//lth[i]表示第 i 短的区间的长度
int main(){
int n,cnt = 0;
cin>>n;
for(int len = 1;len <= n;len = len * 2 + 1){
cnt++;
lth[cnt] = len;
for(int l = 1;l + len - 1 <= n;l++){
v[cnt].push_back(l);//存的东西不重要,能判断有没有构造出这个区间即可
}
s[cnt] = s[cnt - 1] + v[cnt].size();
}
cout<<s[cnt]<<endl;
for(int i=1;i<=cnt;i++){
for(int j : v[i]){
cout<<j<<' '<<j + lth[i] - 1<<endl;
}
}
int q;
cin>>q;
while(q--){
int l,r;
cin>>l>>r;
int len = r - l + 1;
int t = upper_bound(lth,lth + cnt + 1,len) - lth - 1;
cout<<s[t - 1] + l<<" "<<s[t - 1] + l + len - lth[t]<<endl;
}
return 0;
}