Codeforces Round #509 (Div. 2)

题目链接:http://codeforces.com/contest/1041

蒟蒻只会A到E

A

题意:一个商店买的键盘都是连续的,现在被盗了,问你最少可能被盗了多少。

思想:sort  最大减去最小-n+1

题意:给你a,b,x,y,问是否有a<=x && b<=y 满足x/y。

思想:求一下x,y的gcd,然后min(a/temp,b/temp)

C

题意:就是给你n,m,d。就是喝n杯咖啡,然后每个时间都在m范围之内,然后喝两杯咖啡的时间差值最小为d,假如d是3,你在1min喝了咖啡,那么下一杯起码在5喝,第二天一切从0开始。

思想:优先队列,刚开始用了2个优先队列扔皮球,扔T了,后来改成一个扔皮球。判断前边有没有比这个小的时间且符合>d,有的话替换,没有的话新开一天。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
struct node
{
    long long x,y;
    bool operator < (const node & a) const
    {
        return x>a.x;
    }
}a[maxn];
int vis[maxn];
priority_queue <node> q,q1;
int main()
{
	long long n,m,d;
	scanf("%lld%lld%lld",&n,&m,&d);
	int cnt=1;
	for(int i=0;i<n;i++)
	{
		cin>>a[i].x;
		a[i].y=i;
		q.push(a[i]);
	}
	while(!q.empty())
	{
		node temp=q.top();	
		q.pop();
		if(q1.empty())
		{
			vis[temp.y]=cnt++;
			q1.push(temp);
		}
		else
		{
			node T;
			T=q1.top();
			if(temp.x > T.x+d)
			{
				vis[temp.y]=vis[T.y];
				q1.pop();
				q1.push(temp);
			}
			else
			{
				vis[temp.y]=cnt++;
				q1.push(temp);
			}
		}
	} 
	printf("%d\n",cnt-1);
	for(int i=0;i<n;i++)
	{
		if(i)
			printf(" ");
		printf("%d",vis[i]); 
	} 
	printf("\n");
	return 0;
}

D

题意:给你一个高度,然后有n个气旋,在气旋的范围内高度不会下降,问你最远飘多远。

思想:处理下气旋的长度和间隙之间的长度,二分间隙长度就行,在纸上画一画就懂了。n=1的时候特判下。

By passer__, contest: Codeforces Round #509 (Div. 2), problem: (D) Glider, Accepted, #
 #include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
struct node{
	long long l;
	long long r;
	long long cha;
}no[maxn];
long long dp[maxn];
long long ans[maxn];
int main()
{
	int n,h;
	scanf("%d%d",&n,&h);
	for(int i=0;i<n;i++)
		scanf("%lld%lld",&no[i].l,&no[i].r);
	for(int i=0;i<n;i++)
	{
		no[i].cha=no[i].r-no[i].l;
		if(i)
			dp[i]=no[i].l-no[i-1].r;
	}
	long long Max=-1;
	if(n==1)
		printf("%lld\n",min((long long)2e9,h+no[0].r-no[0].l));
	else
	{
		ans[0]=no[0].cha;
		for(int i=1;i<n;i++)
			ans[i]=ans[i-1]+no[i].cha;
		dp[0]=0;
		for(int i=2;i<n;i++)
			dp[i]+=dp[i-1];
		for(int i=1;i<n;i++)
		{
			long long temp=h+dp[i-1];
			long long Temp=lower_bound(dp,dp+n,temp)-dp-1;
			long long TT=ans[Temp]-ans[i-2];
			Max=max(Max,TT);
		}	
		printf("%lld\n",Max+h);
	}	
	return 0;
}

E

题意:一棵树,然后每次切去一条边,然后分成2颗树,然后a代表一棵树最大的节点号,b代表另外的最大的一颗最大的借点号,问你是否可以构成这样的树。

思想:如果max(a,b,不是n的话肯定够不出来,因为不存在那样的树,如果等于的话,贪心考虑,对于没用到的点就存起来,对于用到的点,判断下是否有访问次数-1个点能和他匹配,因为需要构成一条链,当前点和n构成一个链,将那些用不到的放在中间,无论你怎么切,都是当前这个值。

#include<bits/stdc++.h>
#define mmp(x,y) make_pair(x, y)
using namespace std;
const int maxn=1e5+5;
vector<pair<int,int>>V;
int vis[maxn];
int v[maxn]; 
int main() 
{
	int n;
	int flag=1;
	scanf("%d",&n);
	for(int i=1;i<n;i++) 
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(max(a,b)!=n)  
			flag=0;
		int temp=min(a,b);
		vis[temp]++;
	}
	if(flag==0)
	{
		printf("NO\n");
		return 0;
	}
	int top=0;
	for(int i=1;i<n;i++)
	{
		if(vis[i]==0)
		{
			v[++top]=i;
			continue;
		}
		if(top < vis[i]-1)//完犊子 
		{
			printf("NO\n");
			return 0;
		}
		int temp=i;
		int Temp=top-(vis[i]-1);
		for(int j=top;j>Temp;j--) 
		{
			V.push_back(mmp(temp,v[j]));
			temp=v[j];
		}
		V.push_back(mmp(temp,n));
		top=top-(vis[i]-1);
	}
	printf("YES\n");
	for(int i=0;i<V.size(); i++)
		printf("%d %d\n", V[i].first, V[i].second);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值