1、HDU - 5358 *
题意:n个数组成的序列,n<=1e5,1e5>=Ai>=0,求解:(S(i,j)表示和):
思路:
暴力:O(N*N)枚举所有子区间,前缀和求和计算。
思考,log2那个括号就是求i~j区间和的二进制位数,因为所有元素非负,所以二进制位数是在不断增加的,所以可以一层枚举二进制位数,一层尺取数组元素判断区间和的二进制位数是否符合要求,时间复杂度O(T*34*N*34),这样会超时?(显然T取到100就爆炸了)
题解是枚举位数K,同时将K转换为对应的整数范围,然后固定i,在序列上根据该范围在A数组上尺取对应的j的范围L、R,最后计算L、R做出的贡献。
2、HDU 5178
题意:T组输入,N个数组成的序列,其中由多少个不同的数对满足 ,N<=1e5,Xi的绝对值<=1e9。
思路:因为数据量为1e5,所以考虑O(N)或者O(NlogN)的解法。暴力枚举两个数O(N*N)肯定不行。
这题的关键就是看出题目所要求的a<b其实是没有用的,然后我们可以对原序列进行排序,然后二分或者尺取合法区间即可。
AC代码:(二分版本,,,这题二分更好想,但是练习一下尺取呗,,,)
while(t--)
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;++i)cin>>a[i];
LL ans=0;
sort(a+1,a+1+n);
int ff=1;
int tt=1;
for(int i=2;i<=n;++i)
{
LL tmp=a[i]-k;
tmp=lower_bound(a+1,a+i,tmp)-a;
tmp=i-tmp;
ans+=tmp;
}
cout<<ans<<endl;
}
return 0;
3、HDU 1937 (二维尺取)
题意:
思路:
总结来说:
尺取法一般用于枚举区间,求符合限制的区间,“返回值”是区间,整个序列区间要有一定规律,一般也是单调。
二分查值或者枚举合法解,逼近最终答案的思想,序列要求单调。
单调队列一般解决区间内的最值。
单调栈用于求解以某一最值为中心,其所能“管辖”的最大区间。
The end;