【UVA 1451】Average

题意

求长度为n的01串中1占总长(大于L)的比例最大的一个子串起点和终点。

分析

前缀和s[i]保存前i个数有几个1,[j+1,i] 这段区间1的比例就是(s[i]-s[j])/(i-j),于是问题转换为找斜率最大的两个点。

如图,加入j时,就要去掉b1、b2,才能维护斜率的单调递增。

以队列里的点做起点,i 结尾的线段斜率最大的是 i和队列里点组成的下凹线的切线。切点前的点就不会再用到了,因为i后面的点和他们的斜率也将不如和这个切点的斜率。

数形结合,斜率优化,单调队列。

代码

#include<deque>
#include<cstdio>

using namespace std;

deque<int> q;

int s[100005];
int ansl,ansr;

int great(int a,int b,int c,int d)//求ab斜率是否大于cd斜率
{
    return (s[a]-s[b])*(c-d) - (s[c]-s[d])*(a-b);
}

int main()
{
    int t,L,n,a;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d ",&n,&L);
        char cc;
        for(int i=1;i<=n;i++){
            cc=getchar();
            s[i]=s[i-1]+cc-‘0‘;//这样读才不会超时
        }
        q.clear();
        ansl=0;
        ansr=L;
        for(int i=L; i<=n; i++)//以i做线段右端点
        {
            int j=i-L;
            while(q.size()>1)//把j作为线段左端点,加入单调队列
            {//(单调指斜率单调递增)
                int b1=q[q.size()-1];//倒数第1个
                int b2=q[q.size()-2];//倒数第2个
                if(great(b1,b2,j,b1)>0)//如果b1b2斜率比jb1更大
                    q.pop_back();//弹出b1,维护单调性
                else break;//
            }
            q.push_back(j);//j入队
            while(q.size()>1)//去掉队前头不优的起点(线段左端点)
            {//因为和i斜率最大的是下凹线的切点,切点前的点不优
                if(great(i,q[0],i,q[1])<=0)//以i做终点 q[0]i的斜率小于q[1]i的斜率
                    q.pop_front();//就弹出队头
                else break;
            }
            int tmp=great(i,q[0],ansr,ansl);//i和切点的斜率,也就是最大斜率
            if(tmp>0 || tmp==0 && i-q[0]<ansr-ansl)
            {
                ansl=q[0];//左端点更新
                ansr=i;//右端点更新
            }
        }
        printf("%d %d\n",ansl+1,ansr);//存的是左端点右1的点,故输出时+1
    }
    return 0;
}

  

时间: 2024-12-28 21:32:37

【UVA 1451】Average的相关文章

【uva 658】It&#39;s not a Bug, it&#39;s a Feature!(图论--Dijkstra算法+二进制表示)

题意:有n个潜在的bug和m个补丁,每个补丁用长为n的字符串表示.首先输入bug数目以及补丁数目.然后就是对m 个补丁的描述,共有m行.每行首先是一个整数,表明打该补丁所需要的时间.然后是两个字符串,地一个字符串 是对软件的描述,只有软件处于该状态下才能打该补丁该字符串的每一个位置代表bug状态(-代表该位置没bug,+代 表该位置有bug,0表示该位置无论有没有bug都可打补丁).然后第二个字符串是对打上补丁后软件状态的描述 -代表该位置上的bug已经被修复,+表示该位置又引入了一个新的bug

【UVa 10881】Piotr&#39;s Ants

Piotr's Ants Porsition:Uva 10881 白书P9 中文改编题:[T^T][FJUT]第二届新生赛真S题地震了 "One thing is for certain: there is no stopping them;the ants will soon be here. And I, for one, welcome our new insect overlords."Kent Brockman Piotr likes playing with ants. H

【UVa 10815】Andy&#39;s First Dictionary

真的只用set和string就行了. 如果使用PASCAL的同学可能就要写个treap什么的了,还要用ansistring. #include<cstdio> #include<cstring> #include<iostream> #include<string> #include<set> using namespace std; string s; string now; set<string> dict; bool is_al

【UVA - 10815】Andy&#39;s First Dictionary (set)

Andy's First Dictionary Description 不提英文了 直接上中文大意吧 XY学长刚刚立下了再不过CET就直播xx的flag,为了不真的开启直播模式,XY学长决定好好学习英语.于是他每天都读一篇只包含生词的英语文章,并以自己高达450的智商在一秒钟之内记忆下来. 现在给你一篇XY学长今天要读的文章,请你写一个程序,输出他都学习到了哪些单词.要求:如果文章中有相同的单词,那么仅仅输出一次:而且如果两个单词只有大小写不同,将他们视为相同的单词. Input 测试数据将输入

【UVA 1395】 Slim Span (苗条树)

[题意] 求一颗生成树,满足最大边和最小边之差最小 InputThe input consists of multiple datasets, followed by a line containing two zeros separated by a space.Each dataset has the following format.n ma1 b1 w1...am bm wmEvery input item in a dataset is a non-negative integer.

【UVA 1151】 Buy or Build (有某些特别的东东的最小生成树)

[题意] 平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此,你可以新建一些边,费用等于两个端点的欧几里得距离的平方. 另外还有q(0<=q<=8)个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相互连通,第i个套餐的花费为ci. 求最小花费. Input (1 ≤ n ≤ 1000)  (0 ≤ q ≤ 8). The second integer is the the cost of the subnetwork(not greater

【UVA 10369】 Arctic Network (最小生成树)

[题意] 南极有n个科研站, 要把这些站用卫星或者无线电连接起来,使得任意两个都能直接或者间接相连.任意两个都有安装卫星设备的,都可以直接通过卫星通信,不管它们距离有多远. 而安装有无线电设备的两个站,距离不能超过D. D越长费用越多. 现在有s个卫星设备可以安装,还有足够多的无线电设备,求一个方案,使得费用D最少(D取决与所有用无线电通信的花费最大的那条路径). InputThe first line of input contains N, the number of test cases.

【uva 10954】Add All(算法效率+Huffman编码+优先队列)

题意:有N个数,每次选2个数合并为1个数,操作的开销就是这个新的数.直到只剩下1个数,问最小总开销. 解法:合并的操作可以转化为二叉树上的操作[建模],每次选两棵根树合并成一棵新树,新树的根权值等于两棵合并前树的根权值和(也与Huffman编码的建立过程类似,选权值最小的两棵树). 这样总开销就是除了叶子结点的权值和  => 每个叶子结点的权值*层数(根节点层数为0)之和  => WPL(树的所有叶子节点的带权路径长度之和,即该节点到根节点路径长度与节点上权的乘积之和). 而Huffman树就

【uva 10570】Meeting with Aliens(算法效率--暴力+贪心)

题意:输入1~N的一个排列,每次可以交换2个整数,问使排列变成1~N的一个环状排列所需的虽少交换次数.(3≤N≤500) 解法:(又是一道我没打代码,光想和看就花了很久时间的题~QwQ)由于n很小,可以暴力枚举目标的环状排列,于是贪心交换——把元素 x 直接与它的目标位置上的元素互换,这样至少使1个元素的位置正确了.而若 x 先与其他 k 个元素交换,是最多能得到 k+1 个元素的正确排列的,这样并没有之前的策略优.    另外,网上关于此题还有一种关于对链状序列找环的说法,我更加不理解.若有人