A.Berstagram
题意:起始数列是1,2,3,……,n,给你m个操作x,表示将数字x和前一个位置的数交换,如果已经在第一个则不做操作,求每个数能到达的位置的最大和最小值;
分析:扫一遍模拟,更新左右极限;
#include
using namespace std;
const int maxn=1e5+7;
int a[maxn],pos[maxn],l[maxn],r[maxn];
int main()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) a[i]=l[i]=r[i]=i,pos[i]=i;
for(int i=1;i<=m;i++)
{
int x;scanf("%d",&x);
if(a[x]==1) continue;
int s1=a[x];
int y=pos[s1-1];
a[x]--;a[y]++;
l[x]=min(l[x],a[x]);r[x]=max(r[x],a[x]);
l[y]=min(l[y],a[y]);r[y]=max(r[y],a[y]);
swap(pos[s1],pos[s1-1]);
}
for(int i=1;i<=n;i++) printf("%d %d\n",l[i],r[i]);
return 0;
}
B. The Feast and the Bus
题意:一辆巴士可以搭乘一整支或两整支队伍,费用是每一趟的最大承载人数*趟数,求最小费用;
分析:贪心+二分check;如果每次都只搭乘一支队伍,答案可以直接得到;每次可搭乘一支或两支时,按照每支队伍的人数排序,二分巴士的最大承载人数,贪心构造乘车的两支队伍,即就是当前的最大+最小,如果放不下那就是最大单独乘坐,因为最小还可以和次大构造;
#include
using namespace std;
typedef long long ll;
const int maxn=8007;
int num[maxn];
ll rua()
{
int n,k,x,cnt=0;scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&x),num[x]++;
sort(num+1,num+1+k);
int mx=0;
for(int i=1;i+i<=k;i++) mx=max(mx,num[i]+num[k-i+1]);
if(k&1) mx=max(mx,num[k/2+1]);
ll ans=(ll)1e18;
for(int i=num[k];i<=mx;i++)
{
int l=1,r=k,tmp=0;
while(l<=r)
{
tmp++;
if(l!=r && num[l]+num[r]<=i) l++,r--;
else r--;
}
ans=min(ans,1ll*tmp*i);
}
return ans;
}
int main()
{
printf("%lld\n",rua());
return 0;
}
F. Data Center
题意:给你一个矩形面积,求最小周长(整数)
分析:这种都不会干脆别打ACM了
#include
using namespace std;
int main()
{
int n,ans=(int)1e9;scanf("%d",&n);
for(int i=1;i*i<=n;i++) if(n%i==0) ans=min(ans,i+n/i);
printf("%d\n",ans+ans);
}
H. Happy Birthday
题意:给你0~9这10个数字的个数,求不能构造的数中的最小值;
分析:分类讨论;非零数的个数为0时,答案是他本身;按照个数升序+数值升序排序,个数最少的数非零时,答案时个数+1个它本身,否则继续分类:0的个数最小时,如果还有跟他个数相同的x,答案时个数+1个x;否则就是1+(个数+1)个0;
#include
using namespace std;
int cnt[15];
struct node{int num,x;} p[15];
bool cmp(node a,node b) {return a.num==b.num?(a.x0) {printf("%d\n",p[i].x);return;}
if(p[0].x==0)
{
if(p[1].num==p[0].num)
{
while(p[1].num--) printf("%d",p[1].x);
printf("%d\n",p[1].x);return;
}
printf("1");
while(cnt[0]--) printf("0");
printf("0\n");return;
}
while(p[0].num--) printf("%d",p[0].x);
printf("%d\n",p[0].x);return;
}
int main()
{
int t;scanf("%d",&t);
while(t--) rua();
return 0;
}
J. The Parade
题意:给出身高为1~n的人数,要求每一行的人身高差不超过1,并且每一行的人数相同,求最多多少人能进入方阵;
分析:贪心+二分check;二分每一行的人数,记下剩余的人数,如果身高+1的和剩余不能凑成一行,剩余的人就不要;
#include
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
ll a[maxn];
int n;
ll k;
bool check(ll mid)
{
ll cnt=0,res=mid;
for(int i=1;i<=n;i++)
{
ll x=a[i];
if(x>=res) cnt++,x-=res;
cnt+=x/mid;res=mid-x%mid;
if(cnt>=k) return true;
}
return cnt>=k;
}
ll rua()
{
ll sum=0;scanf("%d%lld",&n,&k);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i];
ll l=1,r=sum/k,ans=0;
while(l<=r)
{
ll mid=(l+r)>>1;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
return k*ans;
}
int main()
{
int t;scanf("%d",&t);
while(t--) printf("%lld\n",rua());
return 0;
}
L. Divide The Students
题意:给出a b c三种人数的个数,把他们分成三组,a和c不能分在同一组,问三组人数中最大值的最小值是多少;
分析:贪心+二分check;二分答案,贪心的构造答案,看代码就好了;
#include
using namespace std;
int a,b,c;
bool check(int x)
{
if(a>x && c>x) return false;
int a1=a,b1=b,c1=c;
if(a1>x)
{
a1-=x;
if(a1>x) return false;
if((x-a1)+(x-c1)>=b1) return true;
else return false;
}
else if(c1>x)
{
c1-=x;
if(c1>x) return false;
if((x-c1)+(x-a1)>=b1) return true;
else return false;
}
else if((x-a1)+(x-c1)+x>=b1) return true;
else return false;
}
void rua()
{
scanf("%d%d%d",&a,&b,&c);
int l=(a+b+c+2)/3,r=max({a,b,c}),ans;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
int main()
{
int t;scanf("%d",&t);
while(t--) rua();
return 0;
}