奋斗群群赛—9
T1:Snacktower
题目位置:
题意:
就是给你n个数字,让你建一个塔,从n到底部而且最后再到1,输入天数,如果可以建立塔的话,输出这些部分,如果没有可以建的东西,就输出换行就好了,第i位对应第i天下下来的食物!,求输出策略!见样例:
input:
3
3 1 2
output:
3
2 1
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int a[N],book[N];
int main()
{
int n,max=-1;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
if(max<a[i])
max=a[i];
}
int mx=max;
for(int i=1; i<=n; i++)
{
book[a[i]]=1;
if(a[i]==mx)
{
int j=a[i];
while(book[j]==1)
{
printf("%d ",j);
j--;
mx--;
}
}
printf("\n");
}
return 0;
}
小反思:
这样的处理可以很好的防治TLE的情况,就是这个while循环就好了!
while(book[j]==1)
{
printf("%d ",j);
j--;
mx--;
}
T2:The Queue
题目位置:
题意:
就是有一个人去排队,已知了n个人的队列的排序的方法,然后让你输出这个人在什么时候去能够使他的等待时间能够最短,而注意的是如果他跟了同一个人去的话,他会处于礼貌,排在后面!
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
ll str,end,cost,n;
ll time[100005];
cin>>str>>end>>cost>>n;
end-=cost-1;
if(n==0)
{
cout<<str;
return 0;
}
for(ll i=1; i<=n; i++)
cin>>time[i];
if(time[1]>str)
{
cout<<str;
return 0;
}
ll min=str-time[1]+1;
ll ans=time[1]-1;
ll last=str+cost;
if(min<=0)
{
cout<<str<<endl;
return 0;
}
for(ll i=2; i<=n; i++)
{
if(min>last-time[i]+1)
{
min=last-time[i]+1;
ans=time[i]-1;//排在这个人的前面就好!!
if(min<=0)
{
cout<<ans<<endl;
return 0;
}
}
last+=cost;
if(last>end)
break;
}
if(last<=end)
{
cout<<last<<endl;
return 0;
}
cout<<ans<<endl;
}
小反思:
无,开始就是暴力在每一个人的前面试一试就好了,但是比赛的时候没有想出来!
T3:Garland
题目位置:
题意:
就是有一棵树,每个节点有其自己的权值,有正的还有负的。让你分2刀,让你求分开的3个部分的权值的和相同,为tot/3,让你输出两刀的可能性,注:比如切掉5节点,是指将5节点与其父亲节点变为切断状态!
AC代码:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
const int N=1000005;
int n, root ,tot,v1,v2,temp[N];
//ÀûÓÃtemp µÄÖµÀ´¼Ç¼ i ½ÚµãµÄÊý×ֵĺÍ
vector <int> t[N];
void dfs(int u)
{
for(int i=0; i<t[u].size(); i++)
{
dfs(t[u][i]);
temp[u]+=temp[t[u][i]];
}
if(temp[u]==tot/3&&u!=root)
{
if(v1==0) v1=u,temp[u]=0;
else if(v2==0) v2=u,temp[u]=0;
}
}
int main()
{
scanf("%d",&n);
int f;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&f,&temp[i]);
tot+=temp[i];
t[f].push_back(i);
if(f==0)
root=i;
}
if(tot%3!=0)
{
printf("-1");
return 0;
}
// cout<<root<<endl;
dfs(root);
if(v1 && v2)
printf("%d %d\n",v1,v2);
else
printf("-1");
return 0;
}
小反思:
一开始很多次TLE就是因为所谓的预处理没有处理的特别好所以导致的!相当于每一次都要重新开始算值罢了,而且还单纯的认成了一个二叉树! 如错误代码:
struct light
{
int now,father,temp;
int left;
int right;
} l[N];
long long ligh(int a,int b)
{
light x=l[a];
if(x.left==-1&&x.left==-1)
return x.temp;
long long result=x.temp;
if(x.left!=-1&&x.left!=b) result+=ligh(x.left,b);
if(x.right!=-1&&x.right!=b) result+=ligh(x.right,b);
return result;
}
T4:Cartons of milk
题目位置:
题意:
就是说:某人每天要喝K瓶牛奶,她家里冰箱有n瓶牛奶,超市里有m瓶牛奶。每瓶牛奶有保质期,0就是当天过期,1就是明天过期,以此类推。给出每瓶牛奶的保质期,求她在不让牛奶过期的情况下能够在超市购买的最多牛奶的瓶数以及牛奶的编号。如果她连自己家里冰箱的牛奶也喝不完,输出“-1”。
AC代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <map>
using namespace std;
pair <int,int> market[10000050];
const int N=10000050;
int date[N]={0},sc[N];
int main()
{
int n,m,k,a;
scanf("%d%d%d",&n,&m,&k);
for(int i=1; i<=n; i++)
{
scanf("%d",&a);
date[a]++;
}
//cout<<date[2000045]<<endl;
for(int i=0; i<=10000000; i++)
{
date[i]=date[i]-k; //СÓÚ 0 µÄ²¿·ÖΪҪºÈ¶àÉÙÆ¿ µÄÅ£ÄÌ!
if(date[i]>0)
{
printf("%d",-1);
return 0;
}
}
for(int i=1; i<=m; i++)
{
scanf("%d",&market[i].first);
market[i].second=i;
}
sort(market+1,market+1+m);
int p=0,tot=0;
for(int i=1; i<=m; i++)
{
for(int j=p; j<=market[i].first; j++)
if(date[j]<0)
{
date[j]++;
if(date[j]==0)
while(date[p]==0)
p++;
tot++;
sc[tot]=market[i].second;
break;
}
}
printf("%d\n",tot);
sort(sc+1,sc+1+tot);
for(int i=1; i<=tot; i++)
{
printf("%d ",sc[i]);
}
}
小反思:
类似于贪心,就是将今天要过期的牛奶喝掉,别的就不喝!
T5:Change-free
题目位置:
题意:
有100元的纸币和1元的硬币,颜弋凯大佬有无限多的纸币和 m 个硬币,并决定接下来的 n 天每天花费 c[i] 元。已知收银员在第 i 天找零 x 元的话,不满意度会增加x* w[i],问最小不满意度。最后输出了i天,左边数据表示100钱数,右边表示零钱所示!请记住,会有找钱的情况啊!所以m不是一成不变的!
AC代码:
#include <iostream>
#include <stdio.h>
#include <bits/stdc++.h>
#define ii pair<long ,long long>
using namespace std;
const int N=100005;
priority_queue<int,vector<ii>,greater<ii> > my_quque;
long long ans,i,n,m;
long long angry,cost,note[N+5],coin[N+5];
int main()
{
scanf("%lld%lld",&n,&m);
for(i=1; i<=n; i++)
{
scanf("%lld",&cost);
note[i]=cost/100;
coin[i]=cost%100;
}
for(i=1; i<=n; i++)
{
m-=coin[i]; //减去今天需要的硬币的钱数,m 本来就是总数的意思
scanf("%lld",&angry);
if(coin[i])
{
my_quque.push(ii(angry*(100-coin[i]),i));
}
//假设要找钱,输出了愤怒值以及(100-coin[i])就是找到零钱啊!
//创造了一个优先队列,是小根堆的愤怒值为权值!
if(m<0)
{
m+=100;
ans+=my_quque.top().first;
note[my_quque.top().second]++;
coin[my_quque.top().second]=0;
my_quque.pop();
}
}
printf("%lld\n",ans);
for(int i=1;i<=n;i++)
printf("%lld %lld\n",note[i],coin[i]);
}
小反思:
构造了一个小根堆,first存的是愤怒值最小的情况!second表示的就是i的位置,如果m<0说明此时的钱数是不够的,需要硬币的引入,而且知道m永远不会小于-100,为什么因为coin[i]不是从%100来的吗,所以减数小于100所以不会出现小的情况,只需要加上100就好了!,不足就找钱100元就好了!
m+=100;
ans+=my_quque.top().first;
note[my_quque.top().second]++;
coin[my_quque.top().second]=0;
my_quque.pop();
总结:
1.预处理一定要注意,不然会TLE!
2.还有可以适当学学STL的模板
3.学会暴力解题以及贪心!!