题目链接:http://codeforces.com/contest/1041
蒟蒻只会A到E
A
题意:一个商店买的键盘都是连续的,现在被盗了,问你最少可能被盗了多少。
思想:sort 最大减去最小-n+1
B
题意:给你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;
}