• 题解 UVA1335 【Beijing Guards】


    UVA1335 Beijing Guards

    双倍经验:P4409 [ZJOI2006]皇帝的烦恼

    如果只是一条链,第一个护卫不与最后一个护卫相邻,那么直接贪心,找出最大的相邻数的和。

    当变成环,贪心很容易找到反例(如[5,5,5],贪心答案为10,实际上为15)

    答案存在单调性,考虑二分

    那么怎么判断mid是否合理呢?设mx【i】表示第i个数与第一个数最多可以相同多少个,mn【i】 表示第i个数与第一个数至少相同多少个

    mx[i]=min(a[i],a[1]-mn[i-1]);

    【i-1】最少有mn【i-1】个数与【1】相同,则【i】一定不包括这些数

    mn[i]=max(0,a[1]+a[i-1]-mx[i-1]+a[i]-x);

    a[i-1]-mx[i-1]是【i-1】至少与【1】不同的个数,加上a【1】是【1】与【i-1】所用的最少个数,那么对于【i】,必须有a[1]+a[i-1]-mx[i-1]+a[i]-x个数与【1】相同才能满足x的限制

    那么如果mn【n】==0则说明a[1]+a[i-1]-mx[i-1]+a[i]-x<=0,x可以调小

    当n=1直接输出答案

    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define R register int
    int a[100001],mx[100001],mn[100001],n,l,r,mid;
    inline bool check(int x) {
    	for (R i=2; i<=n; i++) {
    		mx[i]=min(a[i],a[1]-mn[i-1]);
    		mn[i]=max(0,a[1]+a[i-1]-mx[i-1]+a[i]-x);
    	}
    	return !mn[n];
    }
    int main() {
    	while(scanf("%d",&n) && n) {
    		l=0;
    		for (R i=1; i<=n; i++) scanf("%d",&a[i]),l=max(l,a[i]+a[i-1]);
    		if(n==1) {
    			printf("%d
    ",a[1]);
    			continue;
    		}
    		for (mx[1]=mn[1]=a[1],r=300000; l<=r;)
    			if (check(mid=(l+r)>>1)) r=mid-1;
    			else l=mid+1;
    		printf("%d
    ",l);
    	}
    }
    
  • 相关阅读:
    【Java】XML文件的解析
    PE知识复习之PE合并节
    PE知识复习之PE的重定位表
    PE知识复习之PE的两种状态
    PE知识复习之PE的节表
    PE知识复习之PE的各种头属性解析
    PE知识复习之PE的导入表
    PE知识复习之PE的导出表
    PE知识复习之PE的绑定导入表
    第三讲扩展,VA,RVA,FA(RAW),模块地址的概念
  • 原文地址:https://www.cnblogs.com/Randolph68706/p/11439744.html
Copyright © 2020-2023  润新知