Jzoj4845 寻找

来源:互联网 发布:法治知识网络大赛登录 编辑:程序博客网 时间:2024/05/22 06:18
“我有个愿望,我希望穿越一切找到你。”
这是个二维平面世界,平面上有n个特殊的果实,我从(0,0)点出发,希望得到尽量多的果实,但是出于某种特殊的原因,我的运动方式只有三种(假设当前我在(x,y)):
1、我可以走到(x+1,y)
2、我可以走到(x,y+1)
3、我可以走到(x+1,y+1)

现在我需要你的帮助,帮我找出我最多能够得到多少个果实。


经典的二维dp,我们设f[i][j]表示。。。

非常水的一维dp,我们将所有的点按照x排序让后做一次最长不下降子序列就好了

这里比较老实地用了离散化+数据结构,比二分好想多了。。。2333333

#pragma GCC optimize("O3")#pragma G++ optimize("O3")#include<stdio.h>#include<string.h>#include<algorithm>#define N 100010#define mid (l+r>>1) using namespace std;struct dt{ int x,y; } s[N];int n,v[N],r[N],m,w[N<<2],f[N];inline bool c1(dt a,dt b){ return a.x<b.x; }void update(int l,int r,int x,int p,int k){if(l==r){ w[x]=max(w[x],k); return; }if(p<=mid) update(l,mid,x<<1,p,k);  else update(mid+1,r,x<<1|1,p,k);w[x]=max(w[x<<1],w[x<<1|1]);}int query(int l,int r,int x,int L,int R){if(L<=l && r<=R) return w[x];int Ans=0;if(L<=mid) Ans=max(Ans,query(l,mid,x<<1,L,R));if(mid<R) Ans=max(Ans,query(mid+1,r,x<<1|1,L,R));return Ans;}int main(){freopen("find.in","r",stdin);freopen("find.out","w",stdout);scanf("%d",&n);for(int x,y,i=1;i<=n;++i){scanf("%d%d",&x,&y);if(x<0 || y<0){ --n; --i; }else s[i]=(dt){x,y};}sort(s+1,s+1+n,c1);for(int i=1;i<=n;++i) v[i]=s[i].y;sort(v+1,v+1+n); m=unique(v+1,v+1+n)-v-1; for(int i=1;i<=n;++i) r[i]=lower_bound(v+1,v+1+n,s[i].y)-v;for(int i=1;i<=n;++i){ f[i]=query(0,m,1,0,r[i])+1; update(0,m,1,r[i],f[i]); }printf("%d\n",w[1]);}

原创粉丝点击