【JZOJ4845】【NOIP2016提高A组集训第5场11.2】寻找

题目描述

“我有个愿望,我希望穿越一切找到你。”
这是个二维平面世界,平面上有n个特殊的果实,我从(0,0)点出发,希望得到尽量多的果实,但是出于某种特殊的原因,我的运动方式只有三种(假设当前我在(x,y)):
1、我可以走到(x+1,y)
2、我可以走到(x,y+1)
3、我可以走到(x+1,y+1)
现在我需要你的帮助,帮我找出我最多能够得到多少个果实。

数据范围

对于70%的数据1<=n<=1000
对于100%的数据1<=n<=100000,-10^9<=x,y<=10^9

解法

离散化后动态规划,数据结构进行维护。

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="find.in";
const char* fout="find.out";
const int inf=0x7fffffff;
const int maxn=100007,maxt=maxn*4;
int n,i,j,k,num,tot,totx,toty;
int fi[maxn],ne[maxn],la[maxn],en[maxn];
struct point{
    int x,y;
}a[maxn];
bool cmp(point a,point b){
    return a.y<b.y;
}
bool cmp1(point a,point b){
    return a.x<b.x || a.x==b.x && a.y<b.y;
}
void add_line(int a,int b){
    tot++;
    if (fi[a]==0){
        fi[a]=en[a]=tot;
        la[tot]=b;
    }else{
        ne[en[a]]=tot;
        en[a]=tot;
        la[tot]=b;
    }
}
int c[maxt],mark[maxt];
void markdown(int l,int r,int t){
    if (mark[t]==0) return;
    c[t]=max(c[t],mark[t]);
    if (l<r){
        mark[t*2]=max(mark[t*2],mark[t]);
        mark[t*2+1]=max(mark[t*2+1],mark[t]);
    }
    mark[t]=0;
}
int getmax(int l,int r,int t,int v1,int v2){
    int mid=(l+r)/2;
    markdown(l,r,t);
    if (l>v2 || r<v1) return 0;
    if (l>=v1 && r<=v2) return c[t];
    return max(getmax(l,mid,t*2,v1,v2),getmax(mid+1,r,t*2+1,v1,v2));
}
void change(int l,int r,int t,int v1,int v2,int v){
    int mid=(l+r)/2;
    markdown(l,r,t);
    if (l>v2 || r<v1) return;
    if (l>=v1 && r<=v2){
        mark[t]=v;
        markdown(l,r,t);
        return;
    }
    change(l,mid,t*2,v1,v2,v);
    change(mid+1,r,t*2+1,v1,v2,v);
    c[t]=max(c[t*2],c[t*2+1]);
}
int main(){
    freopen(fin,"r",stdin);
    freopen(fout,"w",stdout);
    scanf("%d",&n);
    for (i=1;i<=n;i++){
        scanf("%d%d",&j,&k);
        if (j>=0 && k>=0){
            num++;
            a[num].x=j;
            a[num].y=k;
        }
    }
    sort(a+1,a+num+1,cmp);
    int last=a[1].y;
    a[1].y=1;
    for (i=2;i<=num;i++) if (a[i].y!=last) last=a[i].y,a[i].y=a[i-1].y+1;
    else a[i].y=a[i-1].y;
    toty=a[num].y;
    sort(a+1,a+num+1,cmp1);
    last=a[1].x;
    a[1].x=1;
    add_line(a[1].x,a[1].y);
    for (i=2;i<=num;i++){
        if (a[i].x!=last) last=a[i].x,a[i].x=a[i-1].x+1;
        else a[i].x=a[i-1].x;
        add_line(a[i].x,a[i].y);
    }
    totx=a[num].x;
    for (i=1;i<=totx;i++){
        for (k=fi[i];k;k=ne[k]){
            j=la[k];
            change(1,toty,1,j,toty,getmax(1,toty,1,1,j)+1);
        }
    }
    int ans=getmax(1,toty,1,1,toty);
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/hiweibolu/p/6714856.html