[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\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cold-cold/p/10014492.html