链接:https://ac.nowcoder.com/acm/contest/392/A
解析:
给定n个区间,求覆盖1~n需要最小的区间数目
用贪心解决,l从小到大排,遍历找到 l<=g中r最大的,更新
ac:
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
struct node
{
int l,r;
}ee[MAXN];
bool cmp(node a,node b)
{
return a.l<b.l;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
scanf("%d%d",&ee[i].l,&ee[i].r);
sort(ee,ee+m,cmp);
int flag=0,sum=0,i=0,g=1;
while(i<m)
{
int maxs=0;
for(i;i<m&&ee[i].l<=g;i++)//(i<m)不写会数组溢出
maxs=max(maxs,ee[i].r);
if(maxs==0)
break;
sum++;
g=maxs+1;
if(g>=n)
{
flag=1;
break;
}
}
if(flag)
printf("%d\n",sum);
else
printf("-1\n");
return 0;
}
链接:https://ac.nowcoder.com/acm/contest/984/B
解析:
直接按r排序,切割未被切割过的r最左端的线条
注意不要切割端点,端点被切割不算被切割
ac:
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
struct node
{
int l,r;
int sig=0;
friend bool operator <(node a,node b)
{
return a.r<b.r;
}
}ee[MAXN];
int main()
{
int n,len;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&ee[i].l,&len);
ee[i].r=ee[i].l+len;
}
sort(ee+1,ee+n+1);
int k=0,sum=0;
for(int i=1;i<=n;i++)
{
if(ee[i].l>k)
{
k=ee[i].r-1;//切割端点左边一个位置
sum++;
}
}
printf("%d\n",sum);
return 0;
}
链接:https://ac.nowcoder.com/acm/contest/180/C
解析:
区间贪心,记录a去的位置的最小位置
从左往右扫,目标是r点,如果vis[i]<r,目标就降到vis[i],如果到达r,就ans++,r=vis[i]
ac:
#include<bits/stdc++.h>
using namespace std;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
#define min(a, b) (a < b ? a : b)
char buf[(1 << 22)], *p1 = buf, *p2 = buf;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
#define MAXN 1100005
int vis[MAXN];
int main()
{
int n,m,a,b;
//cin>>n>>m;
n=read();
m=read();
for(int i=0;i<=n;i++)
vis[i]=99999999;
while(m--)
{
//cin>>a>>b;
a=read();
b=read();
vis[a]=min(vis[a],b);
}
int r=99999999,ans=0;
for(int i=1;i<=n;i++)
{
r=min(r,vis[i]);
if(i==r)
{
r=vis[i],ans++;
}
}
cout<<ans<<endl;
return 0;
}
http://codeforces.com/contest/1141/problem/F2
题意:
给一个数组,
求一些不相交的区间,每个区间的和为k,求区间的最大数目
解析:
先求前缀和
两层循环遍历区间,将相同区间和的区间装入vector中
最后遍历每一个区间,贪心求最多区间数目
ac:
#include<bits/stdc++.h>
#define ll long long
#define MAXN 3000005
using namespace std;
struct node
{
int x,y;
bool friend operator <(node a,node b)
{
if(a.y==b.y)
return a.x<b.x;
else return a.y<b.y;
}
};
int a[MAXN];
int sum[MAXN];
map<ll,int> mp;
vector<node> vc[MAXN];
int cnt;
int main()
{
//freopen("E:/in.txt","r",stdin);
cnt=1;
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
int cc=sum[j]-sum[i-1];
if(mp[cc]==0)
{
mp[cc]=cnt;
vc[cnt].push_back({i,j});
cnt++;
}
else{
vc[mp[cc]].push_back({i,j});
}
}
}
int maxs=0,qc,ans=0;
for(int i=1;i<cnt;i++)
{
int len=vc[i].size();
int r=0,sum=0;
sort(vc[i].begin(),vc[i].end());
for(int j=0;j<vc[i].size();j++)
{
if(vc[i][j].x>r)
{
r=vc[i][j].y;
sum++;
}
}
if(sum>ans)
{
ans=sum;
qc=i;
}
}
printf("%d\n",ans);
int r=0;
for(int i=0;i<vc[qc].size();i++)
{
if(vc[qc][i].x>r)
{
printf("%d %d\n",vc[qc][i].x,vc[qc][i].y);
r=vc[qc][i].y;
}
}
return 0;
}