• [POI2005]AUT-The Bus


    题目描述:

      Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到 m编号. 每个路口用两个数(i, j) 表示(1 <= i <= n, 1 <= j <= m). Byte City里有一条公交线, 在某一些路口设置了公交站点. 公交车从 (1, 1) 发车, 在(n, m)结束.公交车只能往北或往东走. 现在有一些乘客在某些站点等车. 公交车司机希望在路线中能接到尽量多的乘客.帮他想想怎么才能接到最多的乘客.

      看完题目后我很高兴,我以为这是到大水题,只不就是一个O(nm)的DP嘛,有什么难的。但当我看到数据范围1n1091≤m≤1091k105 的时候,我就笑不出来了,我立刻想到这一定是一个O(k2)的DP,通过数据结构优化为O(klogk)

    我首先想到的是将整张图按照与对角线平行的线分为n+m-1层,逐层递推,但我很快发现不行,(在笛卡尔坐标系下)如两个点(2,3)和(4,2) ,点2的所在层数比点1大1,按照我的方法点2应该可以从点1转移,但实际上不行,点1不能向下走到点2

    然后我就想到了最长不下降子序列的树状数组优化法,我将x排序后,将y做一个最大子序列(注:不是最长不下降子序列)不就可以了吗?考虑到1≤m≤109所以要离散化

    操作起来,就是dp[i]表示,以x排序后的以第i个点为最后一个节点所能达到的最大值
    转移为在1 - (i-1)中找到y值不大于第i个点y值的点,在其中取最大值再加上p[i],就是dp[i]的值,树状数组优化法较为常见,就不再赘述

    实现如下:

    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <map>
    #include <string>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cstdio>
    #include <cstdlib>
    #define lowbit(x) x&-x
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        register int p(1),a(0);register char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        if(ch=='-') p=-1,ch=getchar();
        while(ch>='0'&&ch<='9') a=a*10+ch-48,ch=getchar();
        return a*p;
    }
    const int N=1000100;
    struct node
    {
        int x,y,p,hao;
        bool operator < (const node xx)const
        {
            return x==xx.x?y<xx.y:x<xx.x;
        }
    }a[N];
    inline int max(int x,int y){return x<y?y:x;}
    int f[N],n,m,k,tt[N],maxn[N],len,ans=0,temp;
    void update(int p,int x)
    {
        for(int i=p;i<=len;i+=lowbit(i))
            maxn[i]=max(x,maxn[i]);
    }
    int query(int p)
    {
        int ans=0;
        for(int i=p;i>=1;i-=lowbit(i))
            ans=max(ans,maxn[i]);
        return ans;
    }
    int main()
    {
        n=read(),m=read(),k=read();
        for(int i=1;i<=k;++i) a[i].x=read(),a[i].y=read(),a[i].p=read();
        sort(a+1,a+1+k);
        for(int i=1;i<=k;++i) tt[i]=a[i].y;
        sort(tt+1,tt+1+k);
        len=unique(tt+1,tt+1+k)-tt-1;
        for(int i=1;i<=k;++i) a[i].hao=lower_bound(tt+1,tt+1+len,a[i].y)-tt-1;
        for(int i=1;i<=k;++i)
        {
            ans=max(ans,temp=a[i].p+query(a[i].y));
            update(a[i].y,temp);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    python数据类型-字典的练习
    python数据类型-元祖和字典类型、hash函数
    python数据类型-字符串
    python数据类型-列表练习
    python数据类型-列表
    iOS 熟悉CASharpLayer
    iOS 点击tableView的cell,让其滚到屏幕顶部
    iOS pop动画之弹性动画的基本使用
    iOS Json解析框架之MJExtension使用详解
    iOS pop动画之衰减动画的基本使用
  • 原文地址:https://www.cnblogs.com/cold-cold/p/10014492.html
Copyright © 2020-2023  润新知