这场比赛发挥的不太好吧,当时只做了两题,第三题当时已经想到正解了,但不知发什么神经去想别的解法了。。。果然晚上的状态不好啊。
A. Cinema Line
非常水……一队人排队买票,每个人只有25、50和100的面值的钱,问买票的人最开始手里没有钱,能否给每个买票的人找钱。直接模拟即可~
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
while(~scanf("%d",&n))
{
int a,b,tmp;
a=b=0;
bool flag=true;
for(int i=1;i<=n;++i)
{
scanf("%d",&tmp);
if(tmp==25)
a++;
else if(tmp==50)
{
b++;
if(a>0) a--;
else flag=false;
}
else
{
if(b>0)
{
if(a>0) b--,a--;
else flag=false;
}
else
{
if(a>2) a-=3;
else flag=false;
}
}
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}
B - Color the Fence
你有v升油漆,可以用这些油漆写数字,给出(1~9)每个数字需要使用的油漆的量,问能写出的最大数字是多少。
我感觉这题很简单啊,但是不知为什么到最后有不少人这题都挂了。最直观的想法就是让每个数字尽量多嘛,这样的话先找出使用油漆最少并且值尽量大的数字,先尽量写这些数字,直到不能写为止,这时有可能还有剩余的油漆,这时只要从最开始看每一位是否能被更大的数字替代就行了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=1000000+10;
struct Node
{
int cost,num;
bool operator < (const Node &a) const
{
return (cost==a.cost&&num>a.num)||(cost<a.cost);
}
};
Node node[10];
int res[maxn],c[10];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int v;
while(~scanf("%d",&v))
{
for(int i=0;i<9;++i)
{
scanf("%d",&node[i].cost);
node[i].num=i+1;
c[i+1]=node[i].cost;
}
sort(node,node+9);
int f=node[0].num;
int cnt=v/node[0].cost;
int r=v-cnt*node[0].cost;
bool find;
if(cnt==0)
{
printf("-1\n");
continue;
}
while(r>0&&cnt>0)
{
find=false;
for(int i=9;i>0;--i)
{
if(i>f&&r+node[0].cost>=c[i])
{
find=true;
printf("%d",i);
r-=(c[i]-node[0].cost);
cnt--;
break;
}
}
if(!find) break;
}
for(int i=0;i<cnt;++i)
printf("%d",f);
printf("\n");
}
return 0;
}
C - Mafia
n个人一起玩游戏,每一轮游戏必须有一个主持人,给出每个人想玩游戏的局数(不当主持人),问至少要多少局比赛才能满足每个人的要求。
n只有10^5,所以可以二分局数,判断这个局数是否能满足所有人要求就行了……
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int num[maxn];
ll sum,maxL;
int n;
bool check(ll m)
{
ll cnt=0;
for(int i=0;i<n;++i)
cnt+=(m-num[i]);
return cnt>=maxL&&cnt>=m;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(~scanf("%d",&n))
{
ll L=0,R=Inf;
sum=0;maxL=0;
for(int i=0;i<n;++i)
{
scanf("%d",&num[i]);
maxL=max(maxL,(ll)num[i]);
sum+=num[i];
}
L=maxL;R=sum;
ll m;
while(L<R)
{
m=(L+R)>>1;
if(check(m))
R=m;
else
L=m+1;
}
printf("%I64d\n",L);
}
return 0;
}
D - Apple Tree
给出一棵树,树上每个叶子节点都有一个权值,给出平衡的定义:一个树平衡,当且仅当对于每一个节点u,都有它的所有的子树,都有相同的权值。问至少要减掉多少权值才能让整棵树平衡。
用val[u]代表节点u子树的总和,fz[u]代表u的总分支数(注意这个分支数并不是实际的分支数)。
看下面的图,这是一个已经处理完的图,每个结点旁边红色的是对应的val[u]的值,紫色的是对应的fz[u]的值。最下面一层很显然是对的,到了第二层,这些结点的权值已经相等了(若不相等需要把他们变为相等),可以发现1结点每次要在其子树中减少权值的话,为了保持平衡,2、3、4这三个分分支要减去相等的值,但这三个结点有些值是不能减的,比如2和3结点,如果要同时减2,可以看到3结点减2是不可能让子树平衡的,因此,每次减的值只能是所有子树分支的最小公倍数,另外还要保证每个分支减的数相同,那么每次要减的最小的数就是:所有子树分支的最小公倍数×分支数。这也就相当于u结点有这些个分支。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
struct Edge
{
int v,next;
};
Edge edges[maxn<<1];
int head[maxn],nEdge;
int w[maxn];
void AddEdge(int u,int v)
{
nEdge++;
edges[nEdge].v=v;
edges[nEdge].next=head[u];
head[u]=nEdge;
}
ll val[maxn],fz[maxn];
ll gcd(ll a,ll b)
{
ll c;
while(b!=0)
{
c=b;
b=a%b;
a=c;
}
return a;
}
ll lcm(ll a,ll b)
{
return a*b/gcd(a,b);
}
void dfs(int u,int fa)
{
ll a=-1,x=-1,b,y;
int child=0;
for(int k=head[u];k!=-1;k=edges[k].next)
{
int v=edges[k].v;
if(v==fa) continue;
child++;
dfs(v,u);
if(a==-1)
a=val[v],x=fz[v];
else
{
b=val[v];y=fz[v];
if(a==0||b==0)
{
a=0;
continue;
}
ll c=min(a,b)-min(a,b)%lcm(x,y);
x=lcm(x,y);
a=c;
}
}
if(child==0)
{
val[u]=w[u];
fz[u]=1;
}
else
{
val[u]=a*child;
fz[u]=x*child;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
while(~scanf("%d",&n))
{
memset(head,0xff,sizeof(head));
nEdge=-1;
ll sum=0;
for(int i=1;i<=n;++i)
{
scanf("%d",&w[i]);
sum+=w[i];
}
int u,v;
for(int i=1;i<n;++i)
{
scanf("%d%d",&u,&v);
AddEdge(u,v);
AddEdge(v,u);
}
dfs(1,-1);
sum-=val[1];
printf("%I64d\n",sum);
}
return 0;
}