hdu1025 Constructing Roads In JGShining's Kingdom

最近准备开始重拾DP,此题本质是求最长上升子序列,用a[u]=v表示当前第u个贫穷的城市对应的对面第v个富裕的城市,然后dp[i]表示当前长度为i时的最小a[k]值,为什么是最小呢?因为只有这样才能保证上升序列达到最长长度,只有尽可能的将dp[len]的值变小才能加入更多的a[i],从而延长数列长度,需要注意最后输出如果只有一条路的话road是没有s的,等到全部扫描完了之后直接打印出最长的长度就可以了

 

#include <iostream>
using namespace std;
const int size = 500000;
int a[size+10];
int dp[size+10];
int search(int x, int left, int right, int *d)//这里使用二分搜索更为优化,下面附有普通搜索也可以过,查找第一个大于等于x的数,然后用x覆盖掉
{
    while (left <= right){
          int mid = (left+right)>> 1;
          if (x >= d[mid])left = mid+1;
          else right = mid-1;     
    }   
    return left;
}
/*int search(int x, int *d, int len)
{
    for (int i = 1; i <= len; i ++){
        if (d[i] >= x)return i;   
    }   
}*/
int main()
{
    int n;
    int nc = 0;
    while (scanf("%d", &n) != EOF){
          for (int i = 1; i <= n; i ++){
              int u, v;
              scanf("%d%d", &u, &v);
              a[u] = v;  
          }    
          int ans = 1;
          dp[1] = a[1];
          for (int i = 2; i <= n; i ++){
              if (a[i] > dp[ans]){
                 ans ++;
                 dp[ans] = a[i];
              }   
              else {//search(a[i], dp, ans)
                   dp[search(a[i], 1, ans, dp)] = a[i];        
              }
          }

//这里有's'的问题要注意下
          if (ans <= 1)
             printf("Case %d:\nMy king, at most %d road can be built.\n\n", ++nc, ans);
          else
              printf("Case %d:\nMy king, at most %d roads can be built.\n\n", ++nc, ans);
    }
    return 0;   
}

你可能感兴趣的:(优化,search)