hdu 4521 小明系列问题——小明序列(线段树)


#include<stdio.h>
#include<string.h>

int A[110000],sum[410000];

int Max(int a,int b){return a<b?b:a;}

void update(int i,int l,int r,int p,int v)
{
    int mid;
    sum[i]=Max(sum[i],v);
    if(l==r)  return ; 
    mid=(l+r)/2;
    if(p<=mid) update(i<<1,l,mid,p,v);
    else update(i<<1|1,mid+1,r,p,v);
}

int query(int i,int l,int r,int a,int b)
{
    int mid;
    if(a>b) return 0;
    if(l==a&&r==b) return sum[i];
    mid=(l+r)/2;
    if(b<=mid) return query(i<<1,l,mid,a,b);
    if(a>mid) return query(i<<1|1,mid+1,r,a,b);
    return Max(query(i<<1,l,mid,a,mid),query(i<<1|1,mid+1,r,mid+1,b));
}
int dp[110000];
int main()
{
    int n,d,i,ans;
    while(scanf("%d%d",&n,&d)!=EOF)
    {
        memset(sum,0,sizeof(sum));
        for(i=1;i<=n;i++)
            scanf("%d",&A[i]);
        ans=0;
        for(i=1;i<=n;i++)
        {
            if(i>d+1)
                update(1,1,100000 + 5,A[i-d-1] + 1,dp[i-d-1]);
            dp[i]=query(1,1,100000 + 5,1,A[i])+1;
            ans=Max(ans,dp[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

版本二:
#include <stdio.h>  
#include <string.h>  
#define MAXN 100010  
#define MAXE 400010  
const int INF = 0x3f3f3f3f;  
struct Node{
	int l,r;
	int max;
}node[MAXE];
int data[MAXN];
int ans[MAXN];
void inite(int root, int l, int r)
{
	node[root].l =l, node[root].r = r;
	node[root].max = 0;
	if(l == r) return ;
	int mid = (l + r) >> 1;
	inite(2 * root, l, mid);
	inite(2 * root + 1, mid + 1, r);
	return ;
}
int query(int root, int pos)
{
	if(node[root].l == node[root].r) return node[root].max;
	int mid = (node[root].l + node[root].r) >> 1;
	if(pos <= mid)
		return query(2 * root, pos);
	int temp = query(2 * root + 1, pos);
	return (temp > node[2 * root].max) ? temp : node[2 * root].max;
}
void insert(int root, int pos, int num)
{
	if(node[root].max < num) node[root].max = num;
	if(node[root].l == node[root].r) return ;
	int mid = (node[root].l + node[root].r) >> 1;
	if(pos <= mid)
		insert(2 * root, pos, num);
	else
		insert(2 * root + 1, pos, num);
}
int main()
{
	int n, d;
	while(~scanf("%d%d", &n, &d))
	{
		int max = 1;
		for(int i = 0; i < n; ++i)
		{
			scanf("%d", &data[i]);
			++data[i];
		}
		inite(1, 0, MAXN);

		for(int i = 0; i < d; ++i)ans[i] = 1;
		for(int i = 0; i < n; ++i)
		{
			if(i - d >= 0)
			{
				ans[i] =1 + query(1, data[i] - 1);
				if(ans[i] > max) max = ans[i];
				insert(1, data[i - d], ans[i - d]);
			}
		}
		printf("%d\n", max);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值