题目大意:某个大学有个2个校区,此大学有n(1<=n<=10000)个运动员,这n个运动员在每个校区都挑选了m(1<=m<=10)个拉拉队。现在每个校区(A/B)中,这m*n个拉拉队按照登记顺序说出自己支持的运动员编号和自己想排在那个位置(输入顺序,m*n*2个数字),排成一列。如果冲突则按照先来后到的顺序依次往后排。求按照A/B的两个拉拉队员站的位置,用他们支持的运动员编号形成的两个序列的最长公共子序列。这道题给4s,20组样例,运算复杂度允许10^7。

思路还是比较明确的。知识点:稀疏序列的匹配,最长上升子序列

第一步:预处理求A/B串。

这个比较好办,如果A(B)列中某君L想在第X个位置:选第X个位置给它,如果X没人占;二分枚举Y(Y>X),X到Y之间空位 = F(Y)-F(X)+1 {F(X)表示1到X之间站的人数},如果X有人站。(树状数组+二分)

第二步:比较A/B。

(最初想法,现在令f(x,y)表示A的前x个数字与B中前y个数字的匹配数,对x从前到后枚举,找B个匹配的y(最多m个),那么f(x,y')=max(f(x,y'),f(x,y-1)+1) {y<=y'<=N=m*n},这不很典型的区间置数问题了吗?solution就很容易想到:线段树。可惜TLE,搓啊!!!!)

首先感谢网上某位大神和我的队友:wonderzy.

最后答案对应的那个目标串中每个匹配的串中每个元素在源串肯定都是有一个下标。

如样例A:3 3 1 1 2 2, B: 3 2 3 1 2 1,最后答案是4,对应着3 3 1 1/3 3 1 2。

其实如果这么A中每一个元素可选在B中的位置(3 1) (3 1) (6 4) (6 4) (5 2) (5 2)。A中每个元素就对应着一个括号,标识着它的可选方案,当然这个元素也可以不选。

这样,结果不就是正好是3 1 3 1 6 4 6 4 5 2 5 2这个串最长上升子序列长度吗?

贴个代码

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=;
struct position{
int id,atx;
}pos[maxn];
int S[maxn*],*pid,N;
#define lowest(x) ((-x)&x)
int sumDown(int x){
int ret=;
while(x>){
ret += S[x];
x -= lowest(x);
}
return ret;
}
void addUp(int x,int id){
pid[x]=id;
while(x <= N){
S[x]++;
x+=lowest(x);
}
}
int findPos(int sf,int left,int right){
int x0=left-;
while(left < right){
int x=(left+right)>>;
int fx=sumDown(x);
if(x-x0 > fx-sf) right=x;
else left=x+;
}
return left;
}
void setOrder(int *A,int m,int n){
pid=A; N=m*n*;
for(int i=N;i>=;i--) S[i]=pid[i]=;
int n2=n*m;
for(int i=;i<n2;i++){
int px=pos[i].atx;
if(!pid[px]) addUp(px,pos[i].id);
else {
int sf=sumDown(px);
px=findPos(sf,px+,N);
addUp(px,pos[i].id);
}
}
int p1=,p2=;
while(p1<n2){
if(pid[p2]) pid[++p1]=pid[p2];
p2++;
}
}
int A[maxn*],B[maxn*],C[maxn*];
int pre[maxn*],head[maxn*];
int gao_LIS(int a[],int len){ //最长公共子序列
int ret=;
int b[maxn];
b[ret++]=a[];
for(int i=;i<len;i++){
int x=lower_bound(b,b+ret,a[i])-b;
if(x==ret){
b[ret++]=a[i];
}else{
b[x]=a[i];
}
}
return ret;
}
int main()
{
int cases; cin>>cases;
int n,m;
for(int cas=;cas<=cases;cas++){
scanf("%d%d",&n,&m);
int n2=m*n;
for(int i=;i<n2;i++) scanf("%d%d",&pos[i].id,&pos[i].atx);
setOrder(A,m,n);
for(int i=;i<n2;i++) scanf("%d%d",&pos[i].id,&pos[i].atx);
setOrder(B,m,n);
//for(int i=1;i<=n2;i++) printf("%d ",A[i]); cout<<endl;
//for(int i=1;i<=n2;i++) printf("%d ",B[i]); cout<<endl;
/******************************/
for(int i=m*n;i>=;i--) head[i]=;
for(int i=;i<=n2;i++)
pre[i]=head[A[i]], head[A[i]]=i;
int idx=;
for(int i=;i<=n2;i++)
for(int j=head[B[i]];j;j=pre[j])
C[idx++]=j;
//for(int i=0;i<idx;i++) cout<<C[i]<<" "; cout<<endl;
printf("Case #%d: %d\n",cas,gao_LIS(C,idx));
/******************************/
}
return ;
}

hdu3525的更多相关文章

随机推荐

  1. 在T-SQL语句中访问远程数据库(openrowset/opendatasource/openquery)

    1.启用Ad Hoc Distributed Queries 在使用openrowset/opendatasource前搜先要启用Ad Hoc Distributed Queries服务,因为这个服务 ...

  2. Binary Tree Level Order Traversal,Binary Tree Level Order Traversal II

    Binary Tree Level Order Traversal Total Accepted: 79463 Total Submissions: 259292 Difficulty: Easy G ...

  3. C++ 多态性浅谈

    多态:一个接口, 多种方法.程序在运行时才决定调用的函数是什么. C++多态通过 虚函数实现, 虚函数允许子类重新定义成员函数, 子类override父类. 多态与非多态的实质区别:函数地址是早绑定还 ...

  4. BullseyeCoverage:代码覆盖率。

    1,安装和使用步骤 阅读READER文档.并安装(非常简单,README中有详细指令说明) 配置环境:同样可以阅读相关文档. 增加PATH环境变量.需要注意,此路径需要增加在PATH的最前列.即< ...

  5. 用记事本编写C#程序并运行C#代码

    net framework自带有C#编译器 csc.exe,用它就好了 它在.NET框架目录下的<\Microsoft.NET\Framework\v**** (*号内容与版本有关) 不行你直接 ...

  6. 京东UED招聘web前端开发工程师(中/高级)

    工作职责: 负责前端界面的构建和各类交互设计与实现: 前端样式和脚本的模块设计及优化: 协同后台开发人员完成项目: 负责新产品开发线前端工作(新产品.垂直站.移动端 .后端系统),可根据个人喜好及特长 ...

  7. python核心编程-第四章-个人笔记

    1.所有的python对象都拥有三个特性: ①身份:每个对象都有唯一的身份标识自己,可用内建函数id()来得到.基本不会用到,不用太关心 >>> a = 2 >>> ...

  8. Hibernate: merge方法

    在Hibernate中,有save.persist.savaOrUpdate.merge等方法有插入数据的功能.前三者理解起来较后者容易一些,merge方法从api中的介绍就看以看出它是最复杂的.下面 ...

  9. RESTful API实现

    RESTful API实现 ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输 ...

  10. 带有OUTPUT的INSERT,DELETE,UPDATE

    原文地址:http://blog.sina.com.cn/s/blog_71460d950100nld2.html OUTPUT是SQL SERVER2005的新特性.可以从数据修改语句中返回输出.可 ...