码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5141——LIS again

时间:2014-12-07 13:51:56      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:dp   线段树   

LIS again

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 132    Accepted Submission(s): 34


Problem Description
A numeric sequence of ai is ordered if a1<a2<<aN. Let the subsequence of the given numeric sequence (a1,a2,,aN) be any sequence (ai1,ai2,,aiK), where 1i1<i2<<iKN. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, eg. (1, 7), (3, 4, 8) and many others.
S[ i , j ] indicates ( ai,ai+1,ai+2,,aj) .
Your program, when given the numeric sequence (a1,a2,,aN), must find the number of pair ( i, j) which makes the length of the longest ordered subsequence of S[ i , j ] equals to the length of the longest ordered subsequence of (a1,a2,,aN).
 

Input
Multi test cases (about 100), every case occupies two lines, the first line contain n, then second line contain n numbers a1,a2,,aN separated by exact one space.
Process to the end of file.

[Technical Specification]
1n100000
0ai1000000000
 

Output
For each case,.output the answer in a single line.
 

Sample Input
3 1 2 3 2 2 1
 

Sample Output
1 3
 

Source
 

Recommend
heyang   |   We have carefully selected several similar problems for you:  5140 5139 5138 5137 5136 
 


线段树+dp,dp[i]表示以第i个元素结尾的LIS的长度,线段树维护此LIS的最靠右的起始位置和长度,靠右是是为了完全统计出这样的区间,最后只要O(n)的时间去统计


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;
const int inf = -0x3f3f3f3f;
int xis[N];
int arr[N];
int dp[N];
int sta[N];
int end[N];
int ans, s;
int cnt;

struct node
{
	int l, r;
	int val, s;
}tree[N << 2];

void build(int p, int l, int r)
{
	tree[p].l = l;
	tree[p].r = r;
	tree[p].val = inf;
	tree[p].s = inf;
	if (l == r)
	{
		return;
	}
	int mid = (l + r) >>1;
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
}

int BinSearch(int val)
{
	int l = 1, r = cnt, mid;
	int ans;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if (xis[mid] > val)
		{
			r = mid - 1;
		}
		else if (xis[mid] < val)
		{
			l = mid + 1;
		}
		else
		{
			ans = mid;
			break;
		}
	}
	return ans;
}

void update(int p, int pos, int val, int s)
{
	if (tree[p].l == tree[p].r)
	{
		if (tree[p].val == val && tree[p].s < s)
		{
			tree[p].s = s;
		}
		else if (tree[p].val < val)
		{
			tree[p].val = val;
			tree[p].s = s;
		}
		return;
	}
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (pos <= mid)
	{
		update(p << 1, pos, val, s);
	}
	else
	{
		update(p << 1 | 1, pos, val, s);
	}
	if (tree[p << 1].val > tree[p << 1 | 1].val)
	{
		tree[p].val = tree[p << 1].val;
		tree[p].s = tree[p << 1].s;
	}
	else if (tree[p << 1].val < tree[p << 1 | 1].val)
	{
		tree[p].val = tree[p << 1 | 1].val;
		tree[p].s = tree[p << 1 | 1].s;
	}
	else
	{
		tree[p].s = max(tree[p << 1].s, tree[p << 1 | 1].s);
	}
}

void query(int p, int l, int r)
{
	if (tree[p].l >= l && tree[p].r <= r)
	{
		if (tree[p].val > ans)
		{
			ans = tree[p].val;
			s = tree[p].s;
		}
		else if (tree[p].val == ans && s < tree[p].s)
		{
			s = tree[p].s;
		}
		return;
	}
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (r <= mid)
	{
		query(p << 1, l, r);
	}
	else if (l > mid)
	{
		query(p << 1 | 1, l, r);
	}
	else
	{
		query(p << 1, l, mid);
		query(p << 1 | 1, mid + 1, r);
	}
}

int main()
{
	int n;
	while (~scanf("%d", &n))
	{
		__int64 ret = 0;
		cnt = 0;
		int tmp = 0;
		for (int i = 1; i <= n; ++i)
		{
			scanf("%d", &arr[i]);
			xis[++cnt] = arr[i];
		}   
		if (n == 1)
		{
			printf("1\n");
			continue;
		}
		sort (xis + 1, xis + cnt + 1);
		cnt = unique(xis + 1, xis + cnt + 1) - xis - 1;
		dp[1] = 1;
		sta[1] = 1;
		build(1, 1, cnt);
		update(1, BinSearch(arr[1]), dp[1], sta[1]);
		for (int i = 2; i <= n; ++i)
		{
			ans = inf;
			s = inf;
			if (BinSearch(arr[i]) == 1)
			{
				dp[i] = 1;
				sta[i] = i;
			}
			else
			{
				query(1, 1, BinSearch(arr[i]) - 1);
			}
			if (ans == inf)
			{
				dp[i] = 1;
				sta[i] = i;
			}
			else
			{
				dp[i] = ans + 1;
				sta[i] = s;
			}
			update(1, BinSearch(arr[i]), dp[i], sta[i]);
			tmp = max(tmp, dp[i]);
		}
		int last = n + 1;
		for (int i = n; i >= 1; --i)
		{
			if (dp[i] == tmp)
			{
				end[i] = last - 1;
				last = i;
			}
		}
		for (int i = 1; i <= n; ++i)
		{
			if (dp[i] == tmp)
			{
				ret += (__int64)sta[i] * (__int64)(end[i] - i + 1);
			}
		}
		printf("%I64d\n", ret);
	}
	return 0;
}


hdu5141——LIS again

标签:dp   线段树   

原文地址:http://blog.csdn.net/guard_mine/article/details/41786567

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!