题意:有n个节目,每个节目有一个持续的天数,你一天只能看一个节目,问你这么多天最多能看几个节目
题解:贪心,我们把那种截止日期最近的节目,都看了。把节目按照截止日期从小到大排序。接下来一个一个节目看,可以用数组标记的方法,for循环判断在当前节目的区间内,还有有没有天数是空闲的。
最后一步的for循环,可以用线段树代替,这样的话就是O(log(k))的效率查找当前节目是否可以观看。 k为区间的长度。
两种方法都可以过
for循环
struct Node
{
int l;
int r;
}b[100005];
int cmp(Node a,Node b)
{
if(a.r==b.r)
return a.l>b.l;
return a.r<b.r;
}
class Solution {
public:
int vis[100005];
int maxEvents(vector<vector<int>>& events) {
int len = 0;
int p = 0;
for(int i=0;i<events.size();i++)
{
len=max(len,events[i][1]);
b[p].l = events[i][0];
b[p].r = events[i][1];
p++;
}
sort(b,b+p,cmp);
int ans=0;
for(int i=0;i<p;i++)
{
for(int j=b[i].l;j<=b[i].r;j++)
{
if(!vis[j])
{
vis[j]=1;
ans++;
break;
}
}
}
return ans;
}
};
线段树
struct Node
{
int l;
int r;
}b[100005];
int cmp(Node a,Node b)
{
if(a.r==b.r)
return a.l>b.l;
return a.r<b.r;
}
class Solution {
public:
int num[100005*4];
int maxEvents(vector<vector<int>>& events) {
int len = 0;
int p = 0;
for(int i=0;i<events.size();i++)
{
len=max(len,events[i][1]);
b[p].l = events[i][0];
b[p].r = events[i][1];
p++;
}
sort(b,b+p,cmp);
int ans=0;
for(int i=0;i<p;i++)
{
int pos = query(1,1,len,b[i].l,b[i].r,0);
if(pos!=-1)
{
ans++;
update(1,1,len,pos,1);
}
}
return ans;
}
void pushup(int node)
{
if(num[node<<1]==num[node<<1|1])
num[node]=num[node<<1];
else
num[node]=-1;
}
void update(int node,int l,int r,int i,int val)
{
if(l==r&&l==i)
{
num[node]=val;
return;
}
int mid = (l+r)/2;
if(i<=mid)
update(node<<1,l,mid,i,val);
if(i>mid)
update(node<<1|1,mid+1,r,i,val);
pushup(node);
}
int query(int node,int l,int r,int start,int end,int val)
{
if(start<=l&&r<=end)
{
if(num[node]!=-1)
{
if(num[node]==val)
return l;
else
return -1;
}
}
int mid = (l+r)/2;
int res;
if(start<=mid)
{
res = query(node<<1,l,mid,start,end,val);
if(res!=-1)
return res;
}
if(end>mid)
{
res = query(node<<1|1,mid+1,r,start,end,val);
}
return res;
}
};