BZOJ2096: [Poi2010]Pilot

111 篇文章 0 订阅
1 篇文章 0 订阅

题目大意:给定n,k和一个长度为n的序列,求最长的最大值最小值相差不超过k的序列


题目显然是个单调队列吗...可以O(N)做....但是那段时间被我用来练习平衡树了...

从前到后扫,每扫到一个就加进来,假如发现相差超过k,就一直在平衡树中删掉队头,总时间复杂度O(NlogN).....

贴一个初期平衡树代码


#include<cstdio>  
#include<cmath>  
#include<iostream>  
#include<cstdlib>  
#define N 3000001  
using namespace std;  
int si[N],ti[N],rd[N],l[N],r[N],a[N],root,cnt;  
int b[N];
void pup(int x)  
{  
    si[x]=si[l[x]]+si[r[x]]+ti[x];  
}  
void zxu(int &k)  
{  
    int t=l[k];  
    l[k]=r[t];  
    r[t]=k;  
    si[t]=si[k];  
    pup(k);  
    k=t;  
}  
void yxu(int &k)  
{  
    int t=r[k];  
    r[k]=l[t];  
    l[t]=k;  
    si[t]=si[k];  
    pup(k);  
    k=t;  
}  
void addadd(int &k,int x)  
{  
    if(!k)  
    {  
        cnt++;  
        k=cnt;  
        a[cnt]=x;  
        si[cnt]=1;  
        ti[cnt]=1;  
        rd[cnt]=rand();  
        return;  
    }  
    si[k]++;  
    if(x==a[k])  
    {  
        ti[k]++;  
        return;  
    }  
    if(x<a[k])  
    {  
        addadd(l[k],x);  
        if(rd[l[k]]>rd[k]) zxu(k);  
    }  
    else
    {  
        addadd(r[k],x);  
        if(rd[r[k]]>rd[k]) yxu(k);  
    }  
}  
void earase(int &k,int x)  
{  
    if(!k) return;  
    if(a[k]==x)  
    {  
        if(ti[k]>1) ti[k]--,si[k]--;  
        else if(l[k]*r[k]==0) k=l[k]+r[k];  
        else if(rd[l[k]]>rd[r[k]])  
        {  
            zxu(k);  
            earase(k,x);  
        }  
        else if(rd[l[k]]<rd[r[k]])  
        {  
            yxu(k);  
            earase(k,x);  
        }  
        return;  
    }  
    if(x>a[k]) si[k]--,earase(r[k],x);  
    else if(x<a[k]) si[k]--,earase(l[k],x);  
}  
int rankgetnum(int k,int x)  
{  
    if(x<=si[l[k]]) return rankgetnum(l[k],x);  
    if(x>si[l[k]]+ti[k]) return rankgetnum(r[k],x-si[l[k]]-ti[k]);  
    return a[k];  
}
int main()  
{  
    int n,m,c;
    cin>>c>>m;
    int i,j,k,x,now=0;
    int ans=0;
    for(i=1;i<=m;i++)
    {
    	now++;
    	scanf("%d",&b[i]);
    	addadd(root,b[i]);
    	while(rankgetnum(root,now)-rankgetnum(root,1)>c)
    	{
	    	now--;
	    	earase(root,b[i-now]);
	    }
	    ans=max(ans,now);
    }
    cout<<ans;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值