zoukankan      html  css  js  c++  java
  • BZOJ 4990 [USACO17FEB] Why Did the Cow Cross the Road II P (树状数组优化DP)

    题目大意:给你两个序列,你可以两个序列的点之间连边

    要求:1.只能在点权差值不大于4的点之间连边

    2.边和边不能相交

    3.每个点只能连一次

    f[i][j]表示第一个序列进行到 i,第二个序列进行到 j,最多连的边数,容易得到方程:

    不连边:f[i][j]=max(f[i-1][j],f[i][j-1]);

    连边:f[i][j]=max(f[i][j],f[i-1][j-1]);

    实际是这样的,每个位置如果想连边,就要从能连边的位置之前找最大值,即f[i][j]=max(f[i-1][k]) (|a[i]-a[j]|<=4,k<j)

    直接转移不可取,由于最多只从9个位置转移,我们可以缩减一维,用f[j]记录b序列进行到位置 的最大连边数,再用树状数组维护f[j]的最大前缀和方便转移

     1 #include <bits/stdc++.h>
     2 #define N 200100
     3 #define ll long long  
     4 using namespace std;
     5 
     6 int n,ans; 
     7 int a[N],b[N],hx[N],f[N],s[N]; 
     8 void update(int x,int w) {for(int i=x;i<=n;i+=(i&(-i))) {s[i]=max(s[i],w);}}
     9 int query(int x) {int ans=0; for(int i=x;i>0;i-=(i&(-i))) {ans=max(ans,s[i]);} return ans;}
    10 
    11 int main()
    12 {
    13     //freopen("Testdata.in","r",stdin);
    14     scanf("%d",&n);
    15     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    16     for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    17     for(int i=1;i<=n;i++) hx[b[i]]=i;
    18     for(int i=1;i<=n;i++)
    19     {
    20         for(int j=max(1,a[i]-4);j<=min(n,a[i]+4);j++) 
    21             f[hx[j]]=query(hx[j]-1); 
    22         for(int j=max(1,a[i]-4);j<=min(n,a[i]+4);j++) 
    23             update(hx[j],f[hx[j]]+1);
    24     }
    25     printf("%d\n",query(n));
    26     return 0;
    27 }
  • 相关阅读:
    MongoDB优化之一:常见优化方法
    Spark Streaming之一:整体介绍
    Java中实现MongoDB自增主键ID
    RDD之一:总体介绍
    对一致性Hash算法,Java代码实现的深入研究
    MongoDB 创建基础索引、组合索引、唯一索引以及优化
    mongo-查询
    MongoTemplate聚合操作
    RESTLET开发实例(一)基于JAX-RS的REST服务
    Hashtable的实现原理
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9696899.html
Copyright © 2011-2022 走看看