HDU 3525 Orienteering (最长公共子串转化为最长上升子序列)

Orienteering


Problem Description
The Orienteering competition is coming soon!Now there are N players to participate in,each has his own cheering squad (lala dui) ,In order to ensure order and security competition,Each player's cheering squad can only send 2*M beautiful mm ,M mm from North Campus,M mm from South Campus(as known that HNU consists of South Campus and North Campus)。
In order to facilitate management , the mm from the same Campus must stay at the same side of the road which means there are two Sequences and each Sequence has equal number of mm .The day of the race,each side has many positions starting from the finishing line toward the starting line numbered for the 1,2,3. . . . up to 2*n*m positions,every mm has her own favorite position,however, when she finds her favorite position is occupied by other students, she has to go to the next position, until she finds a empty position(the cost time of this process is negligible)。
For example, there is a mm whose favorite position is 3,when she goes to the position 3,there has a people over there,so she goes to the next position 4,however ,still has a people there ,until she gets the position 6 where no one occupies this position at present,so she`s position is 6,when all the people find their positions ,the teacher for the competition comes ,he finds that there are still some empty positions ,then he orders that all people move closer to the finishing line which can not change the relative positions of each mm at the both side,so finally their positon number is from 1 to n*m,now we get two sequence A,B A[i] means the mm on the ith position of this side support the player A[i],B[i] means the mm on the ith position of the opposite side support the player B[i].
Now the teacher has Picking a speaker , the mm supporting different players must wear different clothes, but those who support the same player should wear the same clothes. In order to make the venue more harmonious visual effect,to choose two sequence (A[c[1]],A[c[2]],......A[c[len]]) (B[d[1]],B[d[2]],.....B[d[len]]),A[c[i]]=B[d[i]] (1=i<=len) The teacher want to know the max len,can you help us?Namely, you should find the max len such that there exists two identical subsequence with len elements in A and B respectively(these two subsequence need not to be continuous).
 

Input
The first line of input should give the number of cases, T (at most 20).the first line of each case has two numbers n,m(1<=n<=10000,1<=m<=10)n represent the number of players,numbers from 1 to n ,m represent the number of mm of each player`s cheering squad,The next two lines,each with n*m*2 numbers,the i*2-1 number means the ith mm`s supported player number v[i](1<=v[i]<=n),the i*2 number means the ith mm`s faviourite positionw[i](1<=w[i]<=m*n), we set the mm number i is earlier than the mm number j when (i<j).
 

Output
For each case, output should be one line containing "Case #x: ",then flollow a number ,the max len.
 

Sample Input
  
  
1 3 2 1 3 1 4 3 2 2 5 2 2 3 1 3 1 1 4 2 2 3 1 2 4 1 3
 

Sample Output
  
  
Case #1: 4
Hint
After the operation the A sequence is: 3 3 1 1 2 2 While The B sequence is : 3 2 3 1 2 1 The most longest common sequence is 3 3 1 1 so the len is 4.
 

Source
 

Recommend
zhengfeng
 


解题思路:首先预处理产生两个序列,向样例一样:A sequence is: 3 3 1 1 2 2 While The B sequence is : 3 2 3 1 2 1,求A和B的公共序列,效率只能 n*lgn,但是与普通公共序列不同的是,m<=10 ,也就是说有n种,每种m个,充分利用好这个条件,也就是对于B串的每个元素,A串能匹配的公共元素的只能是10个位置,而不是一个串去匹配,这就由原来的n^2降低到 n^10这样,但是还要更新,一开始用线段树,成段更新,超时了,因为线段树乘以的常数有点大,后来再转变思路,到最长上升序列。

对于样例B串的第一个元素3,在A串是 2,1位置,

对于样例B串的第二个元素2,在A串是 6,5位置,

对于样例B串的第三个元素3,在A串是 2,1位置,

.........................................................................

构成的序列就是 2,1,6,5,2,1,4,3,6,5,4,3

就是要求这个序列的最长上升子序列,答案是:1,2,3,4

所以答案是 4


#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
using namespace std;

const int maxn=200100;
vector <int> va,vb,data,dp;
vector <vector <int> > v;
set <int> sa,sb;
int da[maxn],db[maxn],n,m;

void initial(){
	va.clear(),vb.clear();
	sa.clear(),sb.clear();
	v.clear(),data.clear();
	dp.clear();
	for(int i=1;i<=2*n*m;i++){
		da[i]=-1;db[i]=-1;
		sa.insert(i),sb.insert(i);
	}
}

void input(){
	set <int>::iterator it;
	int x,pos;
	for(int i=0;i<n*m;i++){
		scanf("%d%d",&x,&pos);
		if(da[pos]==-1){
			da[pos]=x;
			sa.erase(pos);
		}
		else{
			it=sa.upper_bound(pos);
			da[*it]=x;
			sa.erase(it);
		}
	}
	for(int i=0;i<n*m;i++){
		scanf("%d%d",&x,&pos);
		if(db[pos]==-1){
			db[pos]=x;
			sb.erase(pos);
		}
		else{
			it=sb.upper_bound(pos);
			db[*it]=x;
			sb.erase(it);
		}
	}
	for(int i=1;i<=2*n*m;i++){
		if(da[i]!=-1) va.push_back(da[i]);
		if(db[i]!=-1) vb.push_back(db[i]);
	}
}

void computing(int casen){
	int len=va.size();
	v.resize(n+1);
	for(int i=0;i<len;i++) v[va[i]].push_back(i+1);
	for(int i=0;i<len;i++){
		int s=vb[i];
		for(int t=v[s].size()-1;t>=0;t--){
            data.push_back(v[s][t]);
		}
	}
	dp.push_back(-1);
	for(int i=0;i<data.size();i++){
        int l=0,r=dp.size()-1;
        if(data[i]>dp[r]) dp.push_back(data[i]);
        else{
            while(l<r){
                int mid=(l+r)/2;
                if(data[i]<=dp[mid]) r=mid;
                else l=mid+1;
            }
            dp[r]=data[i];
        }
	}
	printf("Case #%d: %d\n",casen,dp.size()-1);

}

int main(){
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++){
		scanf("%d%d",&n,&m);
		initial();
		input();
		computing(i);
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炒饭君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值