您的位置:首页 > 其它

hdu1025(最长上升子序列)

2014-03-13 14:14 190 查看

Constructing Roads In JGShining's Kingdom

[b]TimeLimit: 2000/1000 MS(Java/Others)    MemoryLimit: 65536/32768 K (Java/Others)

Total Submission(s):7639    AcceptedSubmission(s): 2210
[/b]

Problem Description

JGShining's kingdom consists of 2n(n is no more than 500,000) smallcities which are located in two parallel lines.

Half of these cities are rich in resource (we call them richcities) while the others are short of resource (we call them poorcities). Each poor city is short of exactly one kind of resourceand also each rich city is rich in exactly one kind of resource.You
may assume no two poor cities are short of one same kind ofresource and no two rich cities are rich in one same kind ofresource. 

With the development of industry, poor cities wanna import resourcefrom rich ones. The roads existed are so small that they're unableto ensure the heavy trucks, so new roads should be built. The poorcities strongly BS each other, so are the rich ones. Poor
citiesdon't wanna build a road with other poor ones, and rich ones alsocan't abide sharing an end of road with other rich ones. Because ofeconomic benefit, any rich city will be willing to export resourceto any poor one.

Rich citis marked from 1 to n are located in Line I and poor onesmarked from 1 to n are located in Line II. 

The location of Rich City 1 is on the left of all other cities,Rich City 2 is on the left of all other cities excluding Rich City1, Rich City 3 is on the right of Rich City 1 and Rich City 2 buton the left of all other cities ... And so as the poorones. 

But as you know, two crossed roads may cause a lot of trafficaccident so JGShining has established a law to forbid constructingcrossed roads.

For example, the roads in Figure I are forbidden.



In order to build as many roads as possible, the young and handsomeking of the kingdom - JGShining needs your help, please help him.^_^

 

Input

Each test case will begin with a line containing an integer n(1 ≤ n≤ 500,000). Then n lines follow. Each line contains two integers pand r which represents that Poor City p needs to import resourcesfrom Rich City r. Process to the end of file.

 

Output

For each test case, output the result in the form ofsample. 

You should tell JGShining what's the maximal number of road(s) canbe built. 

 

Sample Input


2 1 22 1 3 1 2 2 3 3 1

 

Sample Output


Case1: My king, at most 1 road can be built. Case 2: My king, at most 2roads can be built.

Hint
Huge input, scanf is recommended.

 

Author

JGShining(极光炫影)

最长上升子序列问题(采用二分查找O(nlogn))

#include <stdio.h>
#include<string.h>
#include<algorithm>
#define MAX 500005
using namespace std;
long n,p,r;
int stack[MAX],g[MAX];
int main(){
long i,w=0;
while(~scanf("%d",&n)){
longlen=1;
for(i=1;i<=n;i++){
scanf("%d%d",&p,&r);
g[p]=r;
}
stack[1]=g[1];
for(i=2;i<=n;i++){
long low=0,mid,high=len;
while(low<=high){
mid=(low+high)>>1;
if(stack[mid]<g[i])
low=mid+1;
else
high=mid-1;
}
stack[low]=g[i];
if(low>len)
len++;
}
w++;
if(len>1)
printf("Case %ld:\nMy king, at most %ld roads canbe built.\n\n",w,len);
else
printf("Case %ld:\nMy king, at most %ld road canbe built.\n\n",w,len);
}
return 0;
}


类似题还有:http://blog.csdn.net/sunacmer/article/details/6846884

下面文章摘自:http://www.slyar.com/blog/longest-ordered-subsequence.html
 

刚才用O(n^2)的DP算法做了最长上升子序列,具体见POJ2533解题报告。后来在网上看到说LIS问题有O(nlogn)的算法,于是拿来小研究了一下。

这个算法其实已经不是DP了,有点像贪心。至于复杂度降低其实是因为这个算法里面用到了二分搜索。本来有N个数要处理是O(n),每次计算要查找N次还是O(n),一共就是O(n^2);现在搜索换成了O(logn)的二分搜索,总的复杂度就变为O(nlogn)了。

这个算法的具体操作如下(by RyanWang):

开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。最长序列长度即为栈的大小top。

这也是很好理解的,对于x和y,如果x < y且Stack[y] <Stack[x],用Stack[x]替换Stack[y],此时的最长序列长度没有改变但序列Q的''潜力''增大了。

举例:原序列为1,5,8,3,6,7

栈为1,5,8,此时读到3,用3替换5,得到1,3,8;再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。

用该算法完成POJ2533的具体代码如下:

#include <iostream>
#define SIZE 1001

using namespace std;

int main(){
int i, j, n, top, temp;

int stack[SIZE];

cin >> n;

top = 0;

stack[0] = -1;

for (i = 0; i < n; i++){

cin >> temp;

if (temp > stack[top]){

stack[++top] = temp;

}
else{

int low = 1, high = top;

int mid;

while(low <= high){

mid = (low + high) / 2;

if (temp > stack[mid]){

low = mid + 1;

}

else{

high = mid - 1;

}

}

stack[low] = temp;

}

}

cout << top << endl;

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: