【AtCoder】【模型转化】【二分答案】Median Pyramid Hard(AGC006)

题意:

给你一个排列,有2*n-1个元素,现在进行以下的操作:

每一次将a[i]替换成为a[i-1],a[i],a[i+1]三个数的中位数,并且所有的操作是同时进行的,也就是说这一次用于计算的a[],是这一次计算之前的那个a[]。每一次不操作开头和结尾的两个位置。这样子每一次都会减少2个元素,问你最后剩下的元素是什么。

数据范围:

1<=N<=10^5

思路:

看见这道题正解是二分的时候,简直震惊!(考试的时候一直想的是计算每一项在最终序列中的系数来做)。

我们可以二分出一个值x,将所有小于等于x的数都变为0,将所有的大于x的数都变为1,然后再来看待这个问题。

下面建议读者一边画图一边来看。

首先定义一种状态,叫做柱子。也就是当存在连续的两个相同的数字的时候,这两个数字的上方会连续出现两个一样的数字,直到成为最左边或者是最右边的数字而被删除为止。

我们考虑哪些状态下,顶层的数字会是0。假如说这个问题解决了,就可以二分了。

1.顶端的正下方就有一根值为0的柱子,这个时候根据柱子的定义是显然成立的;

2.顶端的左边或者是右边有一根值为0的柱子,而另一边没有柱子。如果你画一下图就会发现,对于没有柱子的区域而言,那么必定是0101010...交错排列的。那么当前的这根0的柱子就能够保证到达某一层之后,右边的端点一定是0。这个时候就可以划归到第5种情况了;

3.顶端的两端都有柱子,且都是0的柱子。如果说状态2成立的话,那么这个也是显然成立的;

4.顶端的两端都有柱子,且一边最靠近顶端的柱子值为0,令一端最靠近顶端的柱子值为1,并且要求0柱子更加靠近1柱子。这个比较好想。到达某一层之后,1的柱子消失了,而这个时候0柱子至少还存在1个,且存在1个的时候还是再端右端点上。那么仍然能够划归到情况5;

5.顶端的两端都没有柱子,且底层的两端都是0,也就是num0=num1+1。如果稍微画一下图你就能发现,这样子0101010交错着上去,每一层都是这样子交错的,且都是两端为0。那么这样子到了次顶端的时候必定是010,然后顶端就是0了。

这样子对于一个01的序列直接O(n)判断就好了,总时间为O(nlogn)。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100000
using namespace std;
int N,a[2*MAXN+5];
bool seq[2*MAXN+5];
int Check(int x)
{
    for(int i=1;i<=2*N-1;i++)
        if(a[i]<=x)
            seq[i]=0;
        else
            seq[i]=1;
    if(seq[N]==seq[N-1]||seq[N]==seq[N+1])
        return seq[N];//判断顶端的正下方有没有柱子
    int l=-1,r=-1;
    int ld,rd;
    for(int i=2;i<=N;i++)
        if(seq[i]==seq[i-1])
            l=seq[i],ld=N-i+1;//计算左边的柱子类型以及距离
    for(int i=N;i<2*N-1;i++)
        if(seq[i]==seq[i+1])
        {
            r=seq[i];//计算右边的柱子类型以及距离
            rd=i-N+1;
            break;
        }
    if((l==0&&r==-1)||(l==-1&&r==0)||(l==0&&r==0))//情况2和3
        return 0;
    if((l==1&&r==0&&ld>rd)||(l==0&&r==1&&ld<rd))//情况4
        return 0;
    if(l==-1&&r==-1&&seq[1]==0)//情况5
        return 0;
    return 1;
}
int main()
{
//  freopen("mid.in","r",stdin);
//  freopen("mid.out","w",stdout);
    scanf("%d",&N);
    for(int i=1;i<=2*N-1;i++)
        scanf("%d",&a[i]);
    int L=0,R=2*N;
    while(L<R)
    {
        int mid=(L+R)/2;
        if(Check(mid)==0)//O(n)判断
            R=mid;
        else
            L=mid+1;
    }
    printf("%d\n",R);
    return 0;
}

原文地址:https://www.cnblogs.com/T-Y-P-E/p/10199242.html

时间: 2024-10-08 07:08:38

【AtCoder】【模型转化】【二分答案】Median Pyramid Hard(AGC006)的相关文章

POJ3579 Median(二分答案 + O(N)判定)

传送门 大意:给出N个数,对于存有每两个数的差值的序列求中位数,如果这个序列有偶数个元素,就取中间偏小的作为中位数. 因为N<=100000,所以想要求出每一个差值是不可行的,我们很容易想到二分答案. 在二分答案时我们会进行判定,求出小于等于枚举值的个数,我看其他人的判定似乎都是O(NlogN) 的,我在这里就给出一个O(N)的判定方法. 首先同样将数组排序(我们命名为a数组好了) 我们枚举一个区间[l,r),因为当r增加的时候,要使[l,r)中的数都大于于等于a[r]?枚举值,l必定不会增加,

POJ 3579 Median(二分答案+Two pointers)

[题目链接] http://poj.org/problem?id=3579 [题目大意] 给出一个数列,求两两差值绝对值的中位数. [题解] 因为如果直接计算中位数的话,数量过于庞大,难以有效计算, 所以考虑二分答案,对于假定的数据,判断是否能成为中位数 此外还要使得答案尽可能小,因为最小的满足是中位数的答案,才会是原差值数列中出现过的数 对于判定是不是差值的中位数的过程,我们用尺取法实现. 对于差值类的题目,还应注意考虑边界,即数列只有一位数的情况. [代码] #include <cstdio

Leetcode 4 Median of Two Sorted Arrays 二分查找(二分答案)

貌似是去年阿里巴巴c++的笔试题,没有什么创新直接照搬的... 题意就是找出两个排序数组的中间数,其实就是找出两个排序数组的第k个数. 二分答案,先二分出一个数,再用二分算出这个数在两个排序数组排序第几,然后和k做比较,最后以这个比较为依据接着二分直到求出第k个数. 本来这是两重二分,由于楼主的懒已经没有办法治疗了,用库函数upper_bound()代替了第二重二分,有志者可以自己写第二重二分,楼主就偷懒了... 警告:由于题目很神奇,会出现两个排序数组为空的情况,楼主差点因为这个报警....

【POJ3657】【USACO 2008 Jan Gold】 1.Haybale Guessing 二分答案,并查集check

题意: 输入n.m表示数列长度为n,有m条有序的限制{l,r,x}. 限制:l~r间所有数最小值为x. 问到第几条限制开始出现矛盾,都不出现输出"0". 题解: 首先这题比较厉害,正常解有点难,不妨转化成二分答案. 我们二分"答案",也就是第ans条出现矛盾. 考虑到若一条限制S所在区间被另一个限制Seg包含,且Seg这条限制的x又比S.x大, 那么也就是意为 ① [Seg.l,Seg.r]间最小值为Seg.x ② [S  .l,S  .r]间最小值为S  .x ③

BZOJ 3007 解救小云公主 二分答案+对偶图

题目大意:给定一个矩形和矩形内的一些点.求一条左下角到右上角的路径.使全部点到这条路径的最小距离最大 最小距离最大.果断二分答案 如今问题转化成了给定矩形中的一些圆形障碍物求左下角和右上角是否连通 然后就是对偶图的问题了 左下角和右上角连通等价于对偶图中左上两条边和右下两条边不连通 因此将全部相交的圆之间连边,从左上两条边广搜就可以 时间复杂度O(n^2log(min(r,l)/EPS)) #include <cmath> #include <cstdio> #include &l

bzoj2117 [ 2010国家集训队 ] -- 点分树+二分答案

考虑点分树. 求出每个重心所管辖的范围内的每个点到它的距离,建成点分树. 查询时二分答案,然后问题就转化为求到x的距离<=d的点的个数. 在点分树上暴力往上跑就行了,注意去重. 时间复杂度:O(nlog3n) 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 #include&l

Codeforces Round #425 (Div. 2) Problem C (Codeforces 832C) Strange Radiation - 二分答案 - 数论

n people are standing on a coordinate axis in points with positive integer coordinates strictly less than 106. For each person we know in which direction (left or right) he is facing, and his maximum speed. You can put a bomb in some point with non-n

BZOJ 2402 陶陶的难题II 二分答案+斜率优化+树链剖分+线段树维护凸包

题目大意:给定一棵树,每个点有两个坐标(x1,y1)和(x2,y2),多次询问某条链上选择两个点i和j(可以相同),求(y1i+y2j)/(x1i+x2j)的最大值 我竟没看出来这是01分数规划...真是老了... 二分答案ans,问题转化成验证(y1i+y2j)/(x1i+x2j)是否>=ans 将式子变形可得(y1i-ans*x1i)+(y2j-ans*x2j)>=0 加号两边独立,分别计算即可 问题转化为求链上y-ans*x最大的点 令P=y-ans*x 则y=ans*x+P 我们发现这

POJ 3208 Apocalypse Someday 二分答案+数位DP

这题应该是POJ最强大的一道数位DP了吧 正解是AC自动机 不会 还是写数位DP吧 题目大意:我们令含有666的数字为不吉利数字,则可以得到一个递增数列: {an}=666,1666,2666,3666,4666,5666,6660,6661,.... 给定n,求an 首先我们把这个问题转化成另一个问题:给定n,求1~n中有多少个数含有666 解决了这个问题,把原问题二分答案即可 首先预处理f数组,令 f[i][0]表示i位数中首位不为6且不含666的数的数量 f[i][1]表示i位数中首位连续

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebo