hdu1025(最长上升子序列)

Constructing Roads In JGShining's Kingdom

TimeLimit: 2000/1000 MS(Java/Others)    MemoryLimit: 65536/32768 K (Java/Others)
Total Submission(s):7639    AcceptedSubmission(s): 2210


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.

hdu1025(最长上升子序列)


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; 
    
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值