二分 尺取 单调栈

  • 二分

二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.

void solve()
{
	int lb=-1,ub=n;
	while(ub-lb>1){
		int mid=(ub+lb)/2;
		if(a[mid]>=k){
			ub=mid;
		}
		else{
			lb=mid;
		}
	}
	//lb+1=ub;
 } 

最大化最小值

POJ2456牛舍问题P142:对牛舍位置排序,把第一头放入x0,如果第i头牛放入xj,第i+1头牛就要满足xj+d<=xk的最小的xk中

bool judge(int k)
    {
        int cnt = a[0], num = 1;
        for(int i = 1; i < n; i ++)
        {
            if(a[i] - cnt >= k)
            {
                cnt = a[i];
                num ++;
            }
            if(num >= m) return true;
        }
        return false;
    }
void solve()
    {
        int l = 1, r = a[n-1] - a[0];
        while(l < r)
        {
            int mid = (l+r) >> 1;
            if(judge(mid)) l = mid + 1;
            else r = mid;
        }
        printf("%d\n",r-1);
    }

 最大化平均值

POJ2976例如有 3 场小型比赛,题数分别是 5 题、1 题、6 题,小明预测自己分别能做出 5 题、0题、2题。如果每场都参加,那么大佬度是 ,看着不怎么大佬。不过,如果放弃第 3 场比赛,那么大佬度就是 ,看着更加大佬了。

bool c(double x){
	int i;
	double sum=0;
	for(i=0;i<n;i++) y[i]=a[i]-x*b[i];
	sort(y,y+n);
	for(i=0;i<n-k;i++) sum+=y[n-1-i];
	if(sum>=0) return 1;
	else return 0;
}
int main()
{
	while(scanf("%d%d",&n,&k)!=EOF){
	double mid=0,l=0,r=INF;
	for(i=0;i<100;i++){
		mid=(l+r)/2;
		if(c(mid)) l=mid;
		else r=mid;
	}
    printf("%d\n",m);
    }
	return 0;
}
  • 尺取

POJ3061Subsequence

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.

      while(1)
             {
		while(j<t&&sum<=k)
		{
			sum+=a[j];j++;
		}
		if(sum<k)  break;
		x=min(x,j-i);
		sum-=a[i];i++;
	    }

POJ3320 读书,至少多少页覆盖全部需要看的

        while(1)
	{
		while(j<n&&t<l)
		{
			if(c[a[j]]==0)   t++;
			c[a[j]]++;
		    j++;
		}
		if(t<l)  break;
		ans=min(ans,j-i);
		c[a[i]]--;
		if(c[a[i]]==0)  t--;
		i++;
	}
  • 单调栈

单调栈是一种特殊的栈,特殊之处在于栈内的元素都保持一个单调性。

利用单调栈,可以找到从左/右遍历第一个比它小/大的元素的位

用数组L[i] 表示 第i个数向左遍历的第一个比它小的元素的位置 

一个元素向左遍历的第一个比它小的数的位置就是将它插入单调栈时栈顶元素的值,若栈为空,则说明不存在这么一个数。然后将此元素的下标存入栈,就能类似迭代般地求解后面的元素

Stack<int> S;
    for(int i=1 ;i<=n ;i++){
        while(S.size() && a[S.top()] >= a[i]) S.pop();

        if(S.empty())     L[i] = 0;
        else              L[i] = S.top();

        S.push(i);
    }

POJ3250

for(i=n;i>=0;i--){
        while(s.size()&&a[s.top()]<a[i]) s.pop();
        if(s.empty()) l[i]=0;
        else         l[i]=s.top()-i-1;
        s.push(i);
    }

猜你喜欢

转载自blog.csdn.net/haohaoxuexilmy/article/details/81233736