7.14补题

Codeforces1260D
给出m个士兵,每个士兵有迅捷值ai,士兵可以通过危险值不大于他的陷阱,给出k个陷阱,每个陷阱有位置l,失效的位置r和危险值d,给出t秒从0走到n+1,求最多带几个士兵过去

#include <bits/stdc++.h>
using namespace std;
const int maxn=201000;
int m,n,k,t;
int ai[maxn];
struct node{
    int li,ri,wi;
};
node sum[maxn];
bool cmp(node n1,node n2){
    return n1.li<n2.li;
}
bool scmp(int a,int b){
    return a>b;
}
void init(){
    scanf("%d%d%d%d",&m,&n,&k,&t);
    for(int i=1;i<=m;i++) scanf("%d",&ai[i]);
    sort(ai+1,ai+m+1,scmp);
    for(int i=1;i<=k;i++) scanf("%d%d%d",&sum[i].li,&sum[i].ri,&sum[i].wi);
    sort(sum+1,sum+k+1,cmp);
}
bool check(int mid)
{
    if(mid==0) return true;
    int res=0,l=-1,r=-1;
    for(int i=1;i<=k;i++)
    {
       if(sum[i].wi<=ai[mid]) continue;
       if(l==-1)
       {
           l=sum[i].li;
           r=sum[i].ri;
           continue;
        }
       if(sum[i].li<=r)
           r=max(r,sum[i].ri);
       else
       {
           res+=(r-l+1);
           r=sum[i].ri;
           l=sum[i].li;
       }
    }
    if(l!=-1) res+=(r-l+1);
    return res*2+(n+1)<=t;
}
void solve(){
    int lb=0,rb=m,ans=1;
    while(lb<=rb){
        int mid=(lb+rb)/2;
        if(check(mid))
        {
            ans=mid;
            lb=mid+1;
        }
        else rb=mid-1;
    }
    printf("%d\n",ans);
}

int main(){
    init();
    solve();
    return 0;
}

对题目的细节没有处理好,导致浪费时间,有个注意点是自己可以单独行动到r使陷阱失效,但士兵不能单独行动且选中的所有士兵要一起,因此每遇到一个有士兵不能通过陷阱之前,自己和士兵在同一位置,然后自己单独行动到陷阱失效的位置(前提是这个r没有踩过)再回来,路程要乘2,这就是代码中的res乘2,n+1是自己和士兵一起走过的距离;这个题目还运用了贪心的思想,在决定一个陷阱要不要亲自过去踩的时候,先判断带上的最小的士兵能否直接通过,不能则自己去踩,l,r表示自己走的起点与返回点,这时要走的距离为(r-l+1),但是为了达到贪心的目的,不能直接加到res上,还需要计算下一个陷阱是否也需要这样,如果也需要,再判断第二个陷阱的位置与r的关系,大于r则加到res里,并把l,r更新为第二个陷阱的,小于等于r则可以贪心一次踩多个陷阱,因为 /多个陷阱的单次来回的路程总和 / 必定大于 / 一次走最远的陷阱的失效位置使走过的陷阱失效的路程(/是断句)之后在对时间判断;最后一个关键性的问题士兵数量的选择,将士兵按值降序排之后,注意到带前 i +1个的时间肯定大于等于带前 i 个的,具有单调性,因此可以对士兵人数使用二分法来查找。

Codeforces1257D
给出n个怪兽,每个怪兽有一个力量值,给出m个英雄,每个英雄有力量值可以打过不大于他的怪兽,有耐力值表示每天最多可以打怪兽的数量,每天一个英雄,问最少几天可以打完

#include<bits/stdc++.h>
using namespace std;
const int MAX_N=200005;
int a[MAX_N];//大于等于i的endurance里power的最大值
int m[MAX_N];
int main(){
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m;
		scanf("%d",&n);
		for(int j=0;j<=n;j++)
		    a[j]=m[j]=0;
		for(int j=1;j<=n;j++)
            scanf("%d",&m[j]);
		scanf("%d",&m);
		for(int j=1;j<=m;j++)
		{
			int p,s;
			scanf("%d%d",&p,&s);
			a[s]=max(a[s],p);
		}
		for(int j=n-1;j>=0;j--)
            a[j]=max(a[j+1],a[j]);
		int pos=1,cnt=0;//第pos个怪物
		while(pos<=n){
			cnt++;
			int s=0,maxp=m[pos];//今天可以向前推进ans个怪物
			while(maxp<=a[s+1]&&pos<=n)
            {//如果可以向前推进
				s++;
                pos++;
				maxp=max(maxp,m[pos]);
			}
			if(s==0) break;
		}
		printf("%d\n",pos<=n?-1:cnt);
	}
	return 0;
}

因为每天只可以派一个英雄,所以耐力值相同的情况下,优先选择攻击力高的,用桶排序的思想选,最终得到每个耐力值下的最高攻击力,贪心的关键在于对耐力值贪心,每多判定一个,就找耐力值+1的最高攻击力能否打过,不能就下一天。

CodeForces 1249D2 *
给出n个闭区间,问去掉几个可以使每个点覆盖的区间小于等于k

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int N=2e5+10;
int n,k;
struct Node
{
	int y;
	int idx;
};
bool operator<(Node a,Node b)
{
	if(a.y!=b.y)
		return a.y<b.y;
	return a.idx<b.idx;
}
vector<Node> g[N];
vector<int> ans;
int main()
{
	int x,y;
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		Node p;
		scanf("%d%d",&x,&y);
		p.y=y;
		p.idx=i;
		g[x].push_back(p);
	}
	set<Node> s;
	for(int i=1;i<N;i++)
	{
		while(s.size()&&(*s.begin()).y<i)
			s.erase(*s.begin());

		for(int j=0;j<g[i].size();j++)
			s.insert(g[i][j]);

		while(s.size()>k)
		{
			ans.push_back((*s.rbegin()).idx);
			s.erase(*s.rbegin());
		}
	}
	printf("%d\n",ans.size());
	int len=ans.size();
	for(int i=0;i<len;i++)
	{
		printf("%d%c",ans[i],i==len-1?'\n':' ');
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值