USACO 2017 FEB Platinum nocross DP

  题目大意

    上下有两个长度为n、位置对应的序列A、B,其中数的范围均为1~n。若abs(A[i]-B[j]) <= 4,则A[i]与B[j]间可以连一条边。现要求在边与边不相交的情况下的最大的连边数量。n <= 10^5。

  在Gold里,此题的数据范围是1000,我们完全可以用简单的最长公共连续子序列的DP方法来做。

  范围大了之后,可以观察到对于一个数A[i],它所能转移的状态最多只有9个,那么就可以顺序扫描A数组,设F[i][j]表示当前连得最后一条边为(A[i],B[to[i][j]])的最优解。to[i][j]即A[i]能转移到的B[i]的位置(顺序从小到大)。建立一棵线段树,表示最后连的边中的数B在B数组的位置时,所能得到的最优解。F[i][j]就可以直接logn查询,logn把F[i][j]更新到线段树中。

  

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;

const int maxn = 100005;
int n, a[maxn], b[maxn];
int f[maxn][12], cnt[maxn], to[maxn];
int adj[maxn][12];
struct Tree
{
    int maxv[maxn*4];
    Tree()
    {
        memset(maxv, 0, sizeof(maxv));
    }
    void pushup(int rt)
    {
        maxv[rt] = max(maxv[rt<<1], maxv[(rt<<1)+1]);
    }
    void update(int rt, int l, int r, int p, int d)
    {
        if (l == r)
        {
            maxv[rt] = max(maxv[rt], d);
            return ;
        }
        int mid = (l+r)>>1;
        if (p <= mid)
            update(rt<<1, l, mid, p, d);
        else
            update((rt<<1)+1, mid+1, r, p, d);
        pushup(rt);
    }
    int query(int rt, int l, int r, int L, int R)
    {
        if (L <= l && r <= R)
            return maxv[rt];
        int mid = (l+r)>>1, ret = 0;
        if (L <= mid)
            ret = max(ret, query(rt<<1, l, mid, L, R));
        if (R > mid)
            ret = max(ret, query((rt<<1)+1, mid+1, r, L, R));
        return ret;
    }
}T;

int main()
{
    freopen("nocross.in", "r", stdin);
    freopen("nocross.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &b[i]), to[b[i]] = i;
    for (int i = 1; i <= n; ++i)
    {
        int l = a[i]-4, r = a[i]+4;
        if (l < 0)
            l = 1;
        if (r > n)
            r = n;
        cnt[i] = 0;
        for (int j = l; j <= r; ++j)
            adj[i][++cnt[i]] = to[j];
        sort(adj[i]+1, adj[i]+cnt[i]+1);
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= cnt[i]; ++j)
            if (adj[i][j]-1 >= 1)
                f[i][j] = T.query(1, 1, n, 1, adj[i][j]-1)+1;
            else
                f[i][j] = 0;
        for (int j = 1; j <= cnt[i]; ++j)
            if (adj[i][j]-1 >= 1)
                T.update(1, 1, n, adj[i][j], f[i][j]);
    }
    printf("%d\n", T.maxv[1]);
    return 0;
}

  

时间: 2024-12-17 20:44:39

USACO 2017 FEB Platinum nocross DP的相关文章

USACO 2017 February Platinum

第二次参加USACO 本来打算2016-2017全勤的 January的好像忘记打了 听群里有人讨论才想起来铂金组三题很有意思,都是两个排列的交叉对问题 我最后得分889/1000(真的菜)先发下当时做的,A的之后补 T1.Why Did the Cow Cross the Road题目大意:给出两个N个排列(N<=100,000),允许把其中一个排列循环移动任意位,a[i]表示i在第一个排列中的位置,b[i]表示第二个,定义交叉对(i,j)满足a[i]<a[j]且b[i]>b[j],求

USACO 2017 January Platinum

因为之前忘做了,赶紧补上. T1.Promotion Counting 题目大意:给定一个以1为根的N个节点的树(N<=100,000),每个节点有一个权值,对于每个节点求出权值比它大的子孙的个数. 思路:肯定先要求出dfs序,首先无脑想到主席树,后来发现只要按权值从大到小处理就不用那么麻烦了. #include<cstdio> #include<algorithm> using namespace std; char B[1<<26],*S=B,C;int X;

USACO 2017 FEB Gold visitfj 最短路

题意 有一幅n*n的方格图,n <= 100,每个点上有一个值.从(1,1)出发,走到(n,n),只能走四联通.每走一步花费t,每走三步需要花费走完三步后到达格子的值.求最小花费的值. 拆点,dis[i][j]表示到达第i个点时走的总步数模3等于j时的最小花费值. #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorith

题解 loj3265 3266 3267 USACO 2020.2 Platinum(全)

loj3265 「USACO 2020.2 Platinum」Delegation 因为是最大化最小值,考虑二分答案. 设当前二分的答案为\(K\).则要判断是否有一种划分方式,使得每条链的长度都至少为\(K\). 不妨以\(1\)为根,对整棵树dfs.记\(fa(u)\)为\(u\)的父亲节点.dfs(u)函数求出一个值\(f(u)\),或判断在当前的\(K\)下无解.有解时,我们把\(u\)的子树划分为若干条长度\(\geq K\)的链,并选择一条未完结的链(允许这条链长度\(<K\))覆盖

USACO·2012·Feb Bronze &amp;&amp; 2009·Open Gold

Rope Folding [Brian Dean, 2012] 时间限制: 1 Sec 内存限制: 128 MB 题目描述 Farmer John has a long rope of length L (1 <= L <= 10,000) that he uses for various tasks around his farm. The rope has N knots tied into it at various distinct locations (1 <= N <=

USACO翻译:USACO 2012 FEB Silver三题

USACO 2012 FEB SILVER 一.题目概览 中文题目名称 矩形草地 奶牛IDs 游戏组合技 英文题目名称 planting cowids combos 可执行文件名 planting cowids combos 输入文件名 planting.in cowids.in combos.in 输出文件名 planting.out cowids.out combos.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比较方式 全文比较

BZOJ 1592 Usaco 2008 Feb Making the Grade 路面修整 DP

题目大意:给出一个不整齐的路面,可以将一个路面升高或者降低,都需要话费|x - x'|的费用,把路面修正成单调不降或单调不升的最小花费是多少. 思路:路面的高度跨度有点大啊,先离散化.之后f[i][j] 表示到i为止路面保证单调不降并且最高高度为j的最小花费是多少,利用一个前缀和优化一下.单调不升也一样,简单DP水过.. CODE: #include <map> #include <cstdio> #include <cstring> #include <iost

USACO 2017 December Contest Platinum T2: Push a Box

题目大意 一个谷仓是一个N*M的矩形网格,有一些网格里有干草.Bessie站在其中一个格子内,还有一个格子里有一个大木箱.Bessie不能和大木箱在一个格子里,也不能和干草在一个格子里. 如果她不与干草一个格子,她就可以往自己旁边的四个方向(东西南北)移动,如果她想移动到有木箱的格子里,那个木箱就会被她推一格(只要木箱的那个方向还有空间),如果没有空间,那Bessie就不能移动了. 给你谷仓的布局(空格子,干草以及木箱位置)以及Bessie的出发位置和箱子要被推到的位置,请你帮忙计算Bessie

USACO 2017 December Contest Platinum T3: Greedy Gift Takers

题目大意 有 N(1≤N≤1e5)头牛按顺序排成一列,编号从 1 到 N,1 号牛在队头,N 号牛在队尾. 每次位于队头的牛 i 拿到一个礼物,然后插入到从队尾数ci?头牛之前的位置..举个栗子: 初始队列 1,2,3,4,5 c1?= 2,c2? = 3,则第一次操作后的序列为 2,3,1,4,5,第二次操作后的序列为 3,2,1,4,5.重复无限次操作,求最后有几头牛拿不到礼物. 题目分析 一上来有个显然的结论,若一个人得不到礼物那么原序列中在他后面的人肯定也得不到礼物,因为后面的人跳不到前