树状数组——A

来源:互联网 发布:unity3d如何设置中文 编辑:程序博客网 时间:2024/05/16 10:10
树状数组——A点击打开链接

 第一个自己想思路、没有看过原题博客,完全自己A的树桩数组题!!必须写篇博客纪念一下!!

题意:上下两条直线,编号分别为1-n,从上面一点连接下面一点,每个点只能连一次、求最多可以有多少条线(马路)、

思路:一开始看到,想的是背包、但是数据量太大,背包超时、后来又想用逆序,WA逆序之和,考虑不了前面是否相交、所以不对

仔细分析一下、发现当按下面 的点排序后,再依次看上面的点,对应上面的点如果是最右面一条修的路,那就是左面的点对应的可以修的路的最大值+1、所以树桩数组内保存的该是i到i-=i&(-i)的最大值、

感想:这个题感觉真的有点难度、尤其对于我这种初学者来说、思路太偏了、只这个题,写了三个代码、不过跟后面的题相比、这个又算是简单的了,起码代码短~而且想清楚是最大值问题后,就比较好做了!

 

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iomanip>
#define inf 0x3f3f3f3f
using namespace std;
int N,c[500005];
int max(int aa,int bb)
{
    if(aa>bb) return aa;
    return bb;
}
struct A
{
    int x,y;
}f[500005];
bool cmp(A aa,A bb)
{
    return aa.y<bb.y;
}
int lowbit(int i)
{
    return i&(-i);
}
int big(int i,int j)
{
    int z=0;
       for(;j-lowbit(j)>=i;j-=lowbit(j))
        {z=max(z,c[j]);
        }
        z=max(z,c[j]);
        return z;
}
int add(int i,int s)
{
    while(i<=N)
    {

        c[i]=max(c[i],s);
        i+=lowbit(i);
    }
}
int main()
{
    int i,j,k,T=0,S,l;
    while(~scanf("%d",&N))
    {
        S=0;
        memset(c,0,sizeof(c));
        for(i=1;i<=N;i++)
        scanf("%d%d",&f[i].x,&f[i].y);
        sort(f+1,f+N+1,cmp);
        cout<<"Case "<<++T<<":"<<endl;
        for(i=1;i<=N;i++)
        {
            l=big(1,f[i].x)+1;
            add(f[i].x,l);
            if(S<l) S=l;
        }
        if(S<=1)
            cout<<"My king, at most "<<S<<" road can be built."<<endl;
        else
            cout<<"My king, at most "<<S<<" roads can be built."<<endl;
        cout<<endl;
    }
}

 

原创粉丝点击