zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    Path Sum II
    Convert Sorted Array to Binary Search Tree
    Construct Binary Tree from Inorder and Postorder Traversal
    Construct Binary Tree from Preorder and Inorder Traversal
    Maximum Depth of Binary Tree
    Binary Tree Zigzag Level Order Traversal
    Binary Tree Level Order Traversal
    Same Tree
    Validate Binary Search Tree
    Binary Tree Inorder Traversal
  • 原文地址:https://www.cnblogs.com/cold-cold/p/10014492.html
Copyright © 2011-2022 走看看