点击打开链接
题目和 poj1661 几乎一样 只是数据量加大
每个线段的左右端点找需要落脚点 在poj1661中完全可以依次枚举 但这个过程可以用线段树优化 对于一个端点只需看下面包含它的最高的线段是谁 即区间染色与单点查询
using namespace std;
struct node1
{
int h;
int l;
int r;
int val;
int pl;
int pr;
int maxx;
};
struct node2
{
int l;
int r;
int laz;
int val;
};
node1 line[100010];
node2 tree[400010];
int n;
bool cmp(node1 n1,node1 n2)
{
return n1.h<n2.h;
}
void pushdown(int cur)
{
if(tree[cur].laz)
{
tree[cur*2].laz=tree[cur*2+1].laz=tree[cur].laz;
tree[cur*2].val=tree[cur*2+1].val=tree[cur].laz;
tree[cur].laz=0;
}
return;
}
void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].laz=0;
tree[cur].val=1;
if(l==r) return;
m=(l+r)/2;
build(l,m,cur*2);
build(m+1,r,cur*2+1);
return;
}
int query(int tar,int cur)
{
if(tree[cur].l==tree[cur].r)
{
return tree[cur].val;
}
pushdown(cur);
if(tar<=tree[cur*2].r) return query(tar,cur*2);
else return query(tar,cur*2+1);
}
void update(int ll,int rr,int val,int cur)
{
if(ll<=tree[cur].l&&tree[cur].r<=rr)
{
tree[cur].laz=val;
tree[cur].val=val;
return;
}
pushdown(cur);
if(ll<=tree[cur*2].r) update(ll,rr,val,cur*2);
if(rr>=tree[cur*2+1].l) update(ll,rr,val,cur*2+1);
return;
}
int main()
{
int i;
while(scanf("%d",&n)!=EOF)
{
build(1,100000,1);
for(i=1;i<=n;i++)
{
scanf("%d%d%d%d",&line[i].h,&line[i].l,&line[i].r,&line[i].val);
line[i].pl=-1,line[i].pr=-1,line[i].maxx=0;
}
n++;
line[n].h=0,line[n].l=1,line[n].r=100000,line[n].val=0;
line[n].pl=-1,line[n].pr=-1,line[n].maxx=0;
sort(line+1,line+n+1,cmp);
for(i=2;i<=n;i++)
{
line[i].pl=query(line[i].l,1);
line[i].pr=query(line[i].r,1);
update(line[i].l,line[i].r,i,1);
}
line[n].maxx=line[n].val+100;
for(i=n;i>=2;i--)
{
line[line[i].pl].maxx=max(line[line[i].pl].maxx,line[i].maxx+line[line[i].pl].val);
line[line[i].pr].maxx=max(line[line[i].pr].maxx,line[i].maxx+line[line[i].pr].val);
}
if(line[1].maxx==0)
{
printf("-1\n");
}
else
{
printf("%d\n",line[1].maxx);
}
}
return 0;
}