树状数组——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;
}
}