1 条题解
-
0
自动搬运
来自洛谷,原作者为

greenheadstrange
这个家伙很菜,什么也没有留下搬运于
2025-08-24 21:48:55,当前版本为作者最后更新于2019-06-10 22:17:07,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
很容易想到O(nm)的DP但是一看m和n的范围10^9,GG
再一看k的范围10^5,便想到离散化一下
//本蒟蒻是用map来离散化的,但是推荐dalao们还是用lower_bound比较好 map<int,int>mpx,mpy; for(int i=1;i<=k;i++){ scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].s); x[i]=a[i].x; y[i]=a[i].y; } x[0]=y[0]=1; sort(x,x+k+1); sort(y,y+k+1); mpx[x[0]]=++nx; mpy[y[0]]=++ny; for(int i=1;i<=k;i++){ if(x[i]!=x[i-1])mpx[x[i]]=++nx; if(y[i]!=y[i-1])mpy[y[i]]=++ny; } for(int i=1;i<=k;i++)a[i].x=mpx[a[i].x],a[i].y=mpy[a[i].y];此时的复杂度瞬间降到了O(k^2)但是只有40分,怎么办?
不要慌,先将动态转移方程写出来看看^_^
设f[i]表示走到点i的最大值
将数组a以横坐标作为第一关键字,纵坐标作为第二关键字排序后
f[i]=max(f[j])+a[i].s(其间a[j].y<=a[i].y)
亲爱的童鞋们,看到这里是不是想到了什么优化?
树状数组
sort(a+1,a+k+1,cmp); for(int i=1;i<=k;i++){ f[i]=ask(a[i].y)+a[i].s; modify(a[i].y,f[i]); }下面是本蒟蒻的丑代码:
#include<bits/stdc++.h> using namespace std; const int A=500005; map<int,int>mpx,mpy; struct note{ int x,y,s; }a[A]; int n,m,k,ans,x[A],y[A],c[A*4],f[A],nx,ny; bool cmp(const note&aa,const note&bb){//以横坐标作为第一关键字,纵坐标作为第二关键字排序 return (aa.x==bb.x?aa.y<bb.y:aa.x<bb.x); } ///////////////////////////////树状数组 int lowbit(int x){return x&(-x);}//lowbit操作 void modify(int x,int k){//单点修改 for(int i=x;i<=ny;i+=lowbit(i))c[i]=max(c[i],k); } int ask(int x){//区间查询 int maxx=0; for(int i=x;i;i-=lowbit(i))maxx=max(maxx,c[i]); return maxx; } /////////////////////////////// int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=k;i++){ scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].s); x[i]=a[i].x; y[i]=a[i].y; } ///////////////////////////////离散化 x[0]=y[0]=1; sort(x,x+k+1); sort(y,y+k+1); mpx[x[0]]=++nx; mpy[y[0]]=++ny; for(int i=1;i<=k;i++){ if(x[i]!=x[i-1])mpx[x[i]]=++nx; if(y[i]!=y[i-1])mpy[y[i]]=++ny; } for(int i=1;i<=k;i++)a[i].x=mpx[a[i].x],a[i].y=mpy[a[i].y]; /////////////////////////////// ///////////////////////////////DP sort(a+1,a+k+1,cmp); for(int i=1;i<=k;i++){ f[i]=ask(a[i].y)+a[i].s; modify(a[i].y,f[i]); } for(int i=1;i<=k;i++)ans=max(ans,f[i]); /////////////////////////////// printf("%d",ans); return 0; }结束语:这道题并不难DP+树状数组,但是本蒟蒻却毒瘤了一个小时,结果是粗心将k与n混用了,在此,本蒟蒻提醒您:
代码千万条,细心第一条。
代码不规范,毒瘤两行泪。
- 1
信息
- ID
- 2508
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者