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 }
  • 相关阅读:
    求公约数和比值
    HTML5 文件上传
    js判断是pc还是移动端
    ssm整合
    如何获取数据表中自增主键的值
    MyBatis全局配置文件标签详解
    MyBatis介绍及使用
    基于Spring MVC的文件上传和下载功能的实现
    Spring IOC容器交给application域对象管理
    SpringMVC的简单介绍及使用
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9696899.html
Copyright © 2011-2022 走看看