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$。应用:见到有单调性、有限制的区间问题,很自然地就会想到用尺取去做。