知识点系列——基本算法
2.2 尺取法
HDU-2029 Palindromes _easy version
- 回文数。
void solve() {
cin>>s;
string t=s;
reverse(ALL(t));
if(s==t) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
HDU - 5358 First One
- 因为题目有 $\log$,然后又是双重循环,肯定得优化,因为存在 $\log$,那么又得考虑每一位了。这道题有个特殊的地方就是,我们可以令 $k=(\log_2{S(i,j)}+1),我们可以枚举 $k$ 的值,尺取法选择区间 $[l,r]$ 满足的 $k$,然后固定 $i$ 找 $j$ 满足的区间 $[l,r]$,则在区间中的 $(i+j)=i(r-l+1)+(r-l+1)(l+r)/2$,最后再乘 $k$。
int n,w[N],s[N];
void solve() {
cin>>n;
FOR(i,1,n){
cin>>w[i];
s[i]=s[i-1]+w[i];
}
int ans=0;
FOR(k,1,34){
int L=(1ll<<(k-1)),R=(1ll<<k)-1;
if(k==1)L=0;
int r=1,l=1;
FOR(i,1,n){
l=max(l,i);
while(l<=n&&s[l]-s[i-1]<L)l++;
r=max(r,l);
while(r<=n&&s[r]-s[i-1]>=L&&s[r]-s[i-1]<=R)r++;
if(l<r){
ans+=((r-l)*i+(r-l)*(l+r-1)/2)*k;
}
}
}
cout<<ans<<endl;
}
580B-Kefa and Company
- 题意:给定一些人的钱和贡献,选取一些人让他们的钱之差不超过d,使贡献最大。
- 思路:先按工资升序排序,然后套上尺取就行了,时间复杂度 $O(n\log n)$。
int n,m;
struct E{
int a,b;
bool operator<(const E &x) const {
return a < x.a;
}
}w[N];
int s[N];
void solve() {
cin>>n>>m;
FOR(i,1,n){
cin>>w[i].a>>w[i].b;
}
sort(w+1,w+n+1);
FOR(i,1,n){
s[i]=s[i-1]+w[i].b;
}
int ans=0;
int r=0;
FOR(l,1,n){
while(r<=n&&w[r].a-w[l].a<m){
ans=max(ans,s[r]-s[l-1]);
r++;
}
}
cout<<ans<<endl;
}
……
总结一下尺取法:尺取法的本质就是给定 $l$ ,然后去找满足条件的 $r$。应用:见到有单调性、有限制的区间问题,很自然地就会想到用尺取去做。

浙公网安备 33010602011771号