CodeForces - 1417

CodeForces - 1417

A - Copy-paste

优先把最小的加给别人
再用次小的加给最小的
猜的..

int t,n,k,a[maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        rep(i,1,n)scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        int ans=0;
        rep(i,2,n)ans+=(k-a[i])/a[1],a[i]+=((k-a[i])/a[1])*a[1];
        sort(a+1,a+1+n);
        ans+=(k-a[1])/a[2];
        W(ans);
    }
    return 0;
}



B - Two Arrays

1234...T/2...T
把左边归为一类,右边归为一类,相加起来永远不会为T
如果等于T/2的,如果全分到一边显然是最大的,平分是最小的

int t,n,T,a[maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        int num=0;
        scanf("%d%d",&n,&T);
        rep(i,1,n)scanf("%d",&a[i]);
        rep(i,1,n)if (a[i]==T/2&&T%2==0)num++;
        num/=2;
        if (T%2!=0)
        {
            rep(i,1,n)
            {
                if (a[i]<=T/2)printf("1 ");
                else printf("0 ");
            }
        }
        else
        {
            rep(i,1,n)
            {
                if (a[i]<T/2)printf("1 ");
                else if (a[i]==T/2&&num)
                {
                    printf("%d ",1);
                    num--;
                }
                else printf("0 ");
            }
        }
        puts("");
    }
    return 0;
}



C - k-Amazing Numbers

dis[i]表示i这个数字最多隔几个数字出现一次
例如4 5 5 3 4中 dis[4]=4,dis[3]=4
(不要忘记算开头和结尾)
dis[i]最多隔几个数字的意思就是i可以作为dis[i]+1,dis[i]+2...,n的答案
因为每隔a个数字都会出现i,那么每隔a+1个数字也当然会出现i

const int maxn=3e5+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int dis[maxn],t,n,a[maxn],last[maxn],ans[maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        rep(i,1,n)dis[i]=ans[i]=-1,last[i]=0;
        rep(i,1,n)
        {
            scanf("%d",&a[i]);
            dis[a[i]]=max(dis[a[i]],i-last[a[i]]);
            last[a[i]]=i;
        }
        rep(i,1,n)dis[a[i]]=max(dis[a[i]],n+1-last[a[i]]);//结尾
        rep(i,1,n)
        {
            if (dis[i]==-1)continue;
            rep(j,dis[i],n)
            {
                if (ans[j]!=-1)break;
                ans[j]=i;
            }
        }
        rep(i,1,n)printf("%d ",ans[i]);puts("");
    }
    return 0;
}



D - Make Them Equal

在非1的位置,先用自身的减法和1的减法,把自身变为0
然后最后用1的减法,把非1的位置加到平均值
最多每个位置有3次操作,所以限制了k<3*n

struct node
{
    int x,y,val;
}p[maxn];
int t,n,a[maxn];
vector<node>ans;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        int sum=0;
        ans.clear();
        scanf("%d",&n);
        rep(i,1,n)scanf("%d",&a[i]),sum+=a[i];
        if (sum%n)
        {
            W(-1);
            continue;
        }
        int avg=sum/n;
        rep(i,2,n)
        {
            if (a[i]%i==0)ans.pb(node{i,1,a[i]/i});
            else
            {
                ans.pb(node{1,i,i-(a[i]%i)});
                ans.pb(node{i,1,a[i]/i+1});//顺序不能倒过来
            }
        }
        rep(i,2,n)ans.pb(node{1,i,avg});
        W(ans.size());
        repp(i,0,ans.size())printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].val);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CodeForces - 616D是一个关于找到一个序列中最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段中不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]中不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当前数字在map中不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]中的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值