hdu3525 Orienteering

最长公共子序列nlogn神算法,线段树换了几种姿势,怎么搞都超时,把他转换成LIS就AC了

A :  3 3 1 1 2 2

B :  3 2 3 1 2 1

B中的每个元素在A中的位置倒序再放入B中可得 {2,1}{6,5}{2,1}{4,3}{6,5}{4,3}

我们发现,B中的每一个大括号取一个数,对应A中的匹配加1,而要使A的标号递增,就把每个括号按递减顺序排列,然后对这个序列求LIS就是答案。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <vector>
 5 #include <cstring>
 6 #include <set>
 7 #include <algorithm>
 8 #define maxn 200010
 9 using namespace std;
10 int t,n,m;
11 int fa[maxn],fb[maxn];
12 vector<int> za,zb;
13 vector<int> w[10010];
14 set<int> qa,qb;
15 int v[maxn*5],ct;
16 void init(){
17     za.clear(),zb.clear();
18     memset(fa,0,sizeof fa);
19     memset(fb,0,sizeof fb);
20     qa.clear(),qb.clear();
21     for(int i=0;i<10010;i++) w[i].clear();
22 }
23 void read(){
24     scanf("%d%d",&n,&m);
25     int c,x;
26     for(int i=1;i<=2*n*m;i++) qa.insert(i);
27     for(int i=1;i<=2*n*m;i++) qb.insert(i);
28     for(int i=0;i<n*m;i++){
29        scanf("%d%d",&c,&x);
30        set<int>::iterator at=qa.lower_bound(x);
31        if(at!=qa.end()){
32           fa[*at]=c;
33           qa.erase(at);
34        }
35     }
36     for(int i=0;i<n*m;i++){
37        scanf("%d%d",&c,&x);
38        set<int>::iterator at=qb.lower_bound(x);
39        if(at!=qb.end()){
40           fb[*at]=c;
41           qb.erase(at);
42        }
43     }
44     for(int i=1;i<=2*m*n;i++){
45        if(fa[i]) za.push_back(fa[i]);
46     }
47     for(int i=0;i<n*m;i++){
48        w[za[i]].push_back(i+1);
49     }
50     for(int i=1;i<=2*m*n;i++){
51        if(fb[i]) zb.push_back(fb[i]);
52     }
53 }
54 int gao_LIS(int a[],int len){
55     int ret=0;
56     int b[maxn];
57     b[ret++]=a[0];
58     for(int i=1;i<len;i++){
59         int x=lower_bound(b,b+ret,a[i])-b;
60         if(x==ret){
61            b[ret++]=a[i];
62         }else{
63            b[x]=a[i];
64         }
65     }
66     return ret;
67 }
68 void solve(int ca){
69     ct=0;
70     for(int i=0;i<n*m;i++){
71        int nn=w[zb[i]].size();
72        for(int j=nn-1;j>=0;j--){
73           v[ct++]=w[zb[i]][j];
74        }
75     }
76     printf("Case #%d: %d\n",ca,gao_LIS(v,ct));
77 }
78 int main(){
79     scanf("%d",&t);
80     for(int ca=1;ca<=t;ca++){
81        init();
82        read();
83        solve(ca);
84     }
85     return 0;
86 }
hdu3525

 还有一种线段树做法,

http://wenku.baidu.com/link?url=cZXjwqZqwjIUPS7-pUU4jr7zZD1T7N6Ue635ka2dYm4dZ2d0zVw_0vSJ28rqI57L1KnbVjHp6fh_0-qkkAHIg4QEsvifI5FeuX68C7Ls0sG

转载于:https://www.cnblogs.com/wonderzy/p/3434269.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值