zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 2096 [Poi2010]Pilots

    Description

    Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值。耍畸形一个人是不行的,于是他找到了你。

    Input

    输入:第一行两个有空格隔开的整数k(0<=k<=2000,000,000),n(1<=n<=3000,000),k代表Tz设定的最大值,n代表难度序列的长度。第二行为n个由空格隔开的整数ai(1<=ai<=2000,000,000),表示难度序列。

    Output

    输出:最大的字串长度。

    Sample Input

    3 9
    5 1 3 5 8 6 6 9 10

    Sample Output

    4
    (有两个子串的长度为4: 5, 8, 6, 6 和8, 6, 6, 9.最长子串的长度就是4)

    Solution

    枚举每个点,看以它作为右端点的最优答案是什么
    考虑一个区间,我们其实只需要看最大值和最小值
    如果它们的差不满足要求,那最大值和最小值肯定要走一个,从区间里踢掉,(l) 指针肯定要往右走。假设最大值的位置是 (i) ,最小值的位置是 (j) ,那么 (l) 指针贪心地走到 (min(i,j)+1) 的位置,接着再看区间的最大最小值是否满足要求
    最大值最小值会改变,于是就拿两个单调队列维护单调递增和单调递减,这样踢掉一个最值后,可以马上知道下一个最值
    那这个是 (n^2) 的,因为每次枚举的点都要从头开始考虑
    但我们发现,右端新加进来一个点对于左边不断踢点是没有影响的。右端加进来一个点,不可能会使最优区间的 (l) 还往左走
    所以不需要每个点都从头考虑,直接一遍扫过去然后不停加点就行了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=3000000+10;
    int n,k,A[MAXN],ans,ps=1;
    std::deque<int> q1,q2;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    int main()
    {
    	read(k);read(n);
    	for(register int i=1;i<=n;++i)
    	{
    		read(A[i]);
    		while(!q1.empty()&&A[i]>=A[q1.back()])q1.pop_back();
    		while(!q2.empty()&&A[i]<=A[q2.back()])q2.pop_back();
    		q1.push_back(i);q2.push_back(i);
    		while(A[q1.front()]-A[q2.front()]>k)
    			if(q1.front()<q2.front())ps=q1.front()+1,q1.pop_front();
    			else ps=q2.front()+1,q2.pop_front();
    		chkmax(ans,i-ps+1);
    	}
    	write(ans,'
    ');
    	return 0;
    }
    

    写了单调队列后,发现二分+ST表好像也可以做,二分区间的长度, (O(n)) 枚举左端点,用ST表找最值,看它们的差是否满足要求
    然后写了一下,交一发,结果,卡空间?洛谷RE,BZOJ直接TLE(而且还是只测了1s不到,就直接变成30sTLE,什么操作?)
    所以这个东东就当好玩吧,也没去调细节了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=3000000+10;
    int n,k,A[MAXN],g[MAXN],Mx[MAXN][24],Mn[MAXN][24];
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void init()
    {
    	for(register int i=1;i<=n;++i)g[i]=(int)log2(i);
    	for(register int j=1;j<=22;++j)
    		for(register int i=1;i+(1<<j)-1<=n;++i)
    		{
    			Mx[i][j]=max(Mx[i][j-1],Mx[i+(1<<j-1)][j-1]);
    			Mn[i][j]=min(Mn[i][j-1],Mn[i+(1<<j-1)][j-1]);
    		}
    }
    inline int calc(int l,int len)
    {
    	int r=l+len-1,k=g[len];
    	return max(Mx[l][k],Mx[r-(1<<k)+1][k])-min(Mn[l][k],Mn[r-(1<<k)+1][k]);
    }
    inline bool check(int len)
    {
    	for(register int i=1;i+len-1<=n;++i)
    		if(calc(i,len)<=k)return true;
    	return false;
    }
    int main()
    {
    	read(k);read(n);
    	for(register int i=1;i<=n;++i)
    	{
    		read(A[i]);
    		Mx[i][0]=Mn[i][0]=A[i];
    	}
    	init();
    	int l=1,r=n,ans=1;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(check(mid))ans=mid,l=mid+1;
    		else r=mid-1;
    	}
    	write(ans,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    【20111012】数据库因机器名被修改无法成功发布问题
    SQL Server 2008 r2 bpa 安装
    A faster DBCC CHECKDB? By Ian Stirk, 2011/08/23
    SQL Server 2005 性能故障白皮书
    Best Practices Analyzer Tool for Microsoft SQL Server 2000
    top详细使用说明
    SQLIO测试 SAN
    数据库事务发布性能调整
    查询优化建议
    证书配置数据库镜像 demo from msdn
  • 原文地址:https://www.cnblogs.com/hongyj/p/8979312.html
Copyright © 2011-2022 走看看