楼兰宝藏(Treasure_map.cpp/c/pas) zju2283
【题目描述】
在魔法世界的历史上,楼兰是个充满了神秘色彩的名字。那座昔日绿草遍地人往如织的繁荣古城──楼兰,在公元4 世纪以后,却突然神秘地消失了,留下的只是 “城郭巍然,人物断绝”的不毛之地和难解之谜。
不过著名冒险家席慕蓉在一次探险中发现,原来被沙丘掩埋的楼兰古国地下,埋藏着不计其数的宝藏。
简单说来,就是在一张 N×M的地图,地图上画有P个宝藏(1 ≤ N,M ≤10000000000,P ≤100000),每次当探险者坐标为 (x,y)时,他可以向 (x+1,y)或 (x,y+1)移动一格,问最少要多少次才能拣起所有的宝藏(每次走到最后一步时,会自动传送回左上角位置)。
【输入格式】
第一行有三个整数,分别为N,M,P。余下P行分别为每个宝藏的X、Y坐标。
【输出格式】
一个整数,即次数。
【输入样例】
7 7 7
1 2
1 4
2 4
2 6
4 4
4 7
6 6
【输出样例】
2
【参考代码】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100001],b[100001],link[100001],v[100001],p[100001],tot//v[]用来统计记录序列元素下标
void swap(int &a,int &b)//交换a与b当前的值
{
int t;
t=a;
a=b;
b=t;
}
void init(int n)//初始化,将数组倒叙
{
int t,i;
for(i=1;i<=n;i++)
{
t=b[i];
b[i]=b[n-i+1];
b[n-i+1]=t;
}
}
int find(int key)//二分查找下标
{
int mid,L,R;
L=1;
R=tot;
while(L<=R)
{
mid=(L+R)/2;
if(b[v[mid]]<key)
L=mid+1;
else
R=mid-1;
}
return L-1;
}
void sort(int L,int R)
{
if(L>=R)
return ;
int i,j,k;
k=a[(L+R)/2];
i=L;
j=R;
while(i<=j)
{
while(a[i]<k)
i++;
while(a[j]>k)
j--;
if(i<=j)
{
swap(a[i++],a[j--]);
swap(b[i++],b[j--]);
}
}
sort(L,j);
sort(i,R);
}
int main()
{
//freopen("Treasure_map.in","r",stdin);
//freopen("Treasure_map.out","w",stdout);
int i,j,n,m,k,L;
cin>>n>>m>>k;//有一个m*n的矩阵,有 k个宝藏
for(i=1;i<=k;i++)
cin>>a[i]>>b[i],p[i]=i;//宝藏的坐标a为横坐标,b为纵坐标
sort(1,n);//对横坐标进行排序, 然后以之为权找最长不上升子序列
init(n);
tot=1;
v[tot]=1;
link[1]=p[1];
//tot指最长不上升序列的长度,p[]表示序列的下标,link[]表示连接
for(i=2;i<=k;i++)
{
if(b[p[i]]<=b[v[tot]])
{
tot++;
v[tot]=p[i];
link[p[i]]=v[tot-1];
}
else
{
L=find(b[p[i]]);
v[L+1]=p[i];
link[p[i]]=v[L];
}
}
cout<<tot<<endl;//只需打印长度
return 0;
}
最长不下降子序列