• Jzoj4845 寻找


    “我有个愿望,我希望穿越一切找到你。”
    这是个二维平面世界,平面上有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
    ",w[1]);
    }

  • 相关阅读:
    使用正则表达式实现(加减乘除)计算器(C#实现)
    asp.net core中间件工作原理
    WPF
    WPF
    WPF
    WPF
    WPF 3D Cube及点击交互
    WPF 3D足球导览
    WPF 3D 球面导览
    WPF 3D球及进阶玩法
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/7774321.html
Copyright © 2020-2023  润新知