2 5 1 2 2 2 2 4 3 4 5 1000 5 1 1 2 2 3 3 4 4 5 5
3 1
题意就是求区间的最大值的,可以用线段树+离散化处理,使得坐标区间变小。
如[2,5],[3, 100]离散化后,先排序{2,3,5,100},对应下标值可以变为{1,2,3,4} ,对应时可以去重(见代码)。
区间变为[1,3],[2,4],区间的大小关系不变。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N 200005
#define ll __int64
struct node
{
int l,r;
int v,f; //v记录最大值,f记录当前层累积的值
}f[N*3];
struct st //记录原始区间的左右端点
{
int x,id;
}a[N];
int pos[N/2][2]; //记录区间端点
bool cmp(st a,st b)
{
return a.x<b.x;
}
void creat(int t,int l,int r)
{
f[t].l=l;
f[t].r=r;
f[t].v=f[t].f=0;
if(l==r)
return ;
int tmp=t<<1,mid=(l+r)>>1;
creat(tmp,l,mid);
creat(tmp|1,mid+1,r);
}
void update(int t,int l,int r)
{
int tmp=t<<1,mid=(f[t].l+f[t].r)>>1;
if(f[t].l==l&&f[t].r==r)
{
f[t].v++;
f[t].f++;
return ;
}
if(f[t].f) //下压操作push_down,每次加上累计值
{
f[tmp].v+=f[t].f;
f[tmp|1].v+=f[t].f;
f[tmp].f+=f[t].f;
f[tmp|1].f+=f[t].f;
f[t].f=0; //标记值f置为零
}
if(r<=mid)
update(tmp,l,r);
else if(l>mid)
update(tmp|1,l,r);
else
{
update(tmp,l,mid);
update(tmp|1,mid+1,r);
}
f[t].v=max(f[tmp].v,f[tmp|1].v); //上压操作push_up
}
int main()
{
int T,i,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&pos[i][0],&pos[i][1]);
a[i*2].x=pos[i][0];
a[i*2].id=-(i+1); //记录下标,负值为起点,正值为终点
a[i*2+1].x=pos[i][1];
a[i*2+1].id=i+1;
}
sort(a,a+n*2,cmp);
int t=1,x=a[0].x; //t为重新赋给区间的坐标值
for(i=0;i<n*2;i++)
{
if(x!=a[i].x) //可以达到去除重复值的效果
{
t++;
x=a[i].x;
}
if(a[i].id<0)
pos[-1*a[i].id-1][0]=t;
else
pos[a[i].id-1][1]=t;
}
creat(1,1,n*2);
for(i=0;i<n;i++)
{
update(1,pos[i][0],pos[i][1]);
}
printf("%d\n",f[1].v);
}
return 0;
}
原文:http://blog.csdn.net/u011721440/article/details/41653969