• jzoj 3176. 【GDOI2013模拟5】蜘蛛侠


    Description

    话说世界上有很多超级英雄:蝙蝠侠,蜘蛛侠,超人,名字都写不出来的人等等。在他们之中有一个叫Kickass。今天他想模仿蜘蛛侠,所以他选择了一排高楼来跳。

    具体来说,他选择了一列N幢高楼,从左到右标号为1到N。一开始他在第K幢高楼。不幸的是,Kickass能力非常有限,只能跳到向左或向右相邻的高楼,而且他要跳到的楼的高度必须不能大于他现在处在的楼的高度。Kickass不想自己看起来很渣渣,所以他在一些高楼顶部放了蹦床,从这些高楼起跳,能跳到任何其他的高楼,不管要跳到的高楼在哪里或是多高。

    你的任务是找到Kickass在第K高楼起跳能跳到的最多不同的高楼数。如果Kickass跳到一幢高楼超过一次,我们只会算一次。并且,即使Kickass没有重新跳到,第K幢高楼还是要算入答案。

    Input

    第一行输入两个数:高楼数 N(3<=N<=300,000),起跳位置K(1<=K<=N)。

    第二行包括N个小于10^6的整数,表示1到N高楼的高度。

    第三行包括一行N个字符’.’或’T’。如果第i个字符为’T’,则第i幢楼上有蹦床。

    Output

    输出一行,最多可以跳到的高楼数。

    Sample Input

    输入1:

    6 4

    12 16 16 16 14 14

    .T…

    输入2:

    10 1

    10 7 3 1 1 9 8 2 4 10

    …T…T…

    Sample Output

    输出1:

    5

    输出2:

    7

    Data Constraint

    3<=N<=300,000

    Hint

    第二个样例Kickass经过高楼的顺序:

    1 à 2 à 3 à 6 à 10 à 9 à 8.

    Solution

    这题我们可以找一找规律。
    我们发现:
    如果能够走到一个蹦床的话,我们就可以跳到任何一个蹦床
    而对于一个蹦床,我们可以发现,它的左边不递减以及右边不递增都是可以走到的:
    3 2 1 2 3
    …T…
    就是3跳到5再跑回3,再跳到1再跑回3。
    我们只要分情况(能到蹦床以及不能到蹦床)分开求即可。
    还有,到了蹦床的话,我们发现还有一次机会可以跳到一个点。
    所以,我们再求一下剩下的最长连续不递减或不递增的序列即可。

    Code

    #include<cstdio>
    #include<algorithm>
    #define N 300010
    using namespace std;
    int n,K,a[N],b[N],le,ri,tot=0,j,ma=0,maxx=0;
    int bz[N],ans=0,s=0,s1=0,s2=0;
    bool check[N];
    char c;
    
    inline int read()
    {
    	int x=0,f=0; char c=getchar();
    	while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
    	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return f ? -x:x;
    }
    
    int gsum(int l,int r)
    {
    	int s=0;
    	for (int i=l;i<=r;i++) s+=(!bz[i]);
    	return s;
    }
    
    int gans(int l,int r)
    {
    	int s=0;
    	for (int i=l;i<=r;i++) s+=(bz[i]);
    	return s;
    }
    
    void color(int l,int r) {for (int i=l;i<=r;i++) bz[i]=1;}
    
    int last()
    {
    	int zuo=0,s=0;
    	for (int i=1;i<=n;i++)
    	{
    		if (bz[i])
    		{
    			if (zuo) s=max(s,i-zuo),zuo=0;
    			continue;
    		}
    		if (!zuo) zuo=i;
    		else if (a[i]<a[i-1])
    		{
    			s=max(s,i-zuo),zuo=i;
    			continue;
    		}
    		s=max(s,i-zuo+1);
    	}
    	for (int i=1;i<=n;i++)
    	{
    		if (bz[i])
    		{
    			if (zuo) s=max(s,i-zuo),zuo=0;
    			continue;
    		}
    		if (!zuo) zuo=i;
    		else if (a[i]>a[i-1])
    		{
    			s=max(s,i-zuo),zuo=i;
    			continue;
    		}
    		s=max(s,i-zuo+1);
    	}
    	return s;
    }
    
    int main()
    {
    	freopen("man.in","r",stdin);
    //	freopen("man.out","w",stdout);
    	n=read(),K=read();bz[K]=1;
    	for (int i=1;i<=n;i++) a[i]=read();
    	scanf("
    ");
    	for (int i=1;i<=n;i++)
    		if ((c=getchar())=='T')
    		{
    			bz[i]=check[i]=1;
    			j=i; while (a[j]<=a[j-1] && j>1) j--,bz[j]=1;
    			j=i; while (a[j]<=a[j+1] && j<n) j++,bz[j]=1;
    		}
    	ri=K; while (a[ri]==a[ri+1] && ri<n) ri++,bz[ri]=1,s+=check[ri];
    	le=K; while (a[le]==a[le-1] && le>1) le--,bz[le]=1,s+=check[le];
    	j=le; while (a[j]>=a[j-1] && j>1) j--,s1=check[j] ? j:s1;
    	maxx=ri-j+1;
    	if (s1) ma=gsum(s1,le-1);
    	j=ri; while (a[j]>=a[j+1] && j<n) j++,s2=check[j] ? j:s2;
    	maxx=max(maxx,j-le+1);
    	if (s2 && gsum(ri+1,j)>ma) color(ri+1,s2);
    	else if (ma) color(s1,le-1);
    	if (s1 || s2 || s) printf("%d
    ",gans(1,n)+last());
    	else printf("%d
    ",maxx);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    BZOJ 2306 幸福路径(DP)
    BZOJ 2303 方格染色(带权并查集)
    2011 Multi-University Training Contest 8
    POJ 1379 Run Away(模拟退火)
    BZOJ 3680 吊打XXX(模拟退火)
    POJ 3074 Sudoku(Dancing Links)
    java 基础语法 1
    java 配置环境变量
    windows 结束进程的详细过程
    在同一台服务器上配置多个Tomcat
  • 原文地址:https://www.cnblogs.com/jz929/p/11817539.html
Copyright © 2020-2023  润新知