首页 > 其他分享 >Codeforces Round #768 (Div. 2)C ,D

Codeforces Round #768 (Div. 2)C ,D

时间:2022-12-26 18:14:08浏览次数:58  
标签:768 return int sum Codeforces mid maxn Div include

Codeforces Round #768 (Div. 2)C ,D

C

C

这一道题的大意是从0到n-1,(n一定是2的x次方),我需要找n/2对数对,使得每一个数对(x,y),x&y的和要等于k(k<=n-1)

我一开始是没什么思路的,直到我看了大佬的讲解,ε=(´ο`*)))唉

下面是我的理解

n=8时

000和111(0和7)

001和110(1和6)

010和101(2和5)

011和100(3和4)

这些对进行&的值都是0,而且每一个都是i和n-i-1,所以当k=0时,答案就是每一个(i,n-i-1)

又因为1111&x=x

所以当k<n-1我们可以让k和n-1配对,那么而原本要和k配对的n-k-1和原本要和n-1配对的0就配对(刚好0&n-k-1=0,其他的也一定会是0)

而当k=n-1时n-1是最大的,而&一定会比n-1少,那么我们必须由两个部分来组成,1和n-2

那么我们可以这样

 cout<<n-2<<" "<<n-1<<'\n';//这个是n-2,还剩1(下面配对),0没有配对对象
 cout<<1<<" "<<3<<'\n';//这个是1,还剩n-2(上面已经配对),n-4没有配对对象
 cout<<0<<" "<<n-4<<'\n';//0和n-4配对

其他的按照原来的配对方式来

#include <iostream>
#include <vector>
using namespace std;
const int maxn=2e5+10;
int t,n,k;
void solve()
{
    cin>>n>>k;
    if (n==4&&k==3)
    {
        cout<<-1<<'\n';
        return ;
    }
    if (k==0)
    {
        for (int i=0;i<n/2;i++)
        {
            cout<<i<<" "<<n-i-1<<'\n';
        }
    }
    else if (k<n-1)
    {
        cout<<0<<" "<<n-k-1<<'\n';//这一个是把原来和k配对,和n-1配对的来配对,刚好交换了原来0和n-1的配对对象
        cout<<k<<" "<<n-1<<'\n';//k&(n-1)=k
        for (int i=1;i<n/2;i++)
        {
            if (i!=k&&(n-i-1)!=k)
            {
                cout<<i<<" "<<n-i-1<<'\n';
            }
        }
    }
    else if (k==n-1)//k=n-1,n-1是最大的,而&一定会比n-1少,那么我们必须由两个部分来组成,1和n-2
    {
        cout<<n-2<<" "<<n-1<<'\n';//这个是n-2,还剩1(下面配对),0没有配对对象
        cout<<1<<" "<<3<<'\n';//这个是1,还剩n-2(上面已经配对),n-4没有配对对象
        cout<<0<<" "<<n-4<<'\n';//0和n-4配对
        cout<<2<<" "<<n-3<<'\n';
        for (int i=4;i<n/2;i++)
        {
            cout<<i<<" "<<n-i-1<<'\n';
        }
    }
    return ;
}
int main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

D

D

这题的大意是有一个数组,我们需要把这个数组分成k份,而我们则需要得到一个范围[x,y],只要每一份里面的数其中在这一个范围里的数量大于不在这个范围的数量就可以了,我们需要输出min(y-x)的符号以上条件的x,y然后再输出每一份的l,r

假如p是在[x,y]里的数量,q是不在[x,y]里的数量,那么对于一份,就是p-q>=1,对于k组(n个所有的数),那么就是p-q>=k,而我们要求这n个数里在[x,y]范围的数量,我这里用到了前缀和,而对于寻找min(y-x),这里用到了二分,这样求出了min(y-x),然后我们只需要求出k-1份l,r最后一份就是k-1的r+1到n

对于每一份的l,r的寻找,我们只需要模拟,一旦p>q,就把此时的l,r存进去,然后更新l

具体看代码

对于那一个求前缀和来判断这一对[x,y]是否符合条件,我是觉得太妙了,好聪明的想法

#include <iostream>
#include<vector>
// #include <pair>
using namespace std;
const int maxn=2e5+10;
int n,k,a[maxn],sum[maxn];
pair<int,int>b[maxn];
int t;
inline bool check(int x,int y)
{
    int d=sum[y]-sum[x-1];
    if (2*d-n>=k) return true;//d-(n-d)>=k
    return false;
}
void solve()
{
    cin>>n>>k;
    sum[0]=0;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[i]=0;
    }
    for (int i=1;i<=n;i++)
    {
        sum[a[i]]++;
    }
    for (int i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]+sum[i];
    }
    pair<int,int>ans;
    ans={1,n};
    for (int x=1;x<=n;x++)
    {
        int l=x,r=n;
        int ansr=r;
        while (l<=r)
        {
            int mid=(l+r)>>1;
            if (check(x,mid))
            {
                r=mid-1;
                ansr=mid;
            }
            else l=mid+1;
        }
        if (check(x,ansr))
        {
            int len=ansr-x;
            int lenn=ans.second-ans.first;
            if (len<lenn)
            {
                ans={x,ansr};
            }
        }
    }
    int cnt=0;
    int x=ans.first,y=ans.second;
    int l=1,sum=0;
    for (int i=1;i<=n;i++)
    {
        if (a[i]>=x&&a[i]<=y) sum++;
        else sum--;
        if (sum>0)
        {
            b[++cnt]={l,i};
            sum=0,l=i+1;
            if (cnt==k-1) break;
        }
    }
    cout<<x<<" "<<y<<'\n';
    for (int i=1;i<k;i++)
    {
        cout<<b[i].first<<" "<<b[i].second<<'\n';
    }
    cout<<b[k-1].second+1<<" "<<n<<'\n';
    return ;
}
int main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

标签:768,return,int,sum,Codeforces,mid,maxn,Div,include
From: https://www.cnblogs.com/righting/p/17006362.html

相关文章

  • Codeforces - 542C - Idempotent functions(思维 + 数学、*2000)
    542C-Idempotentfunctions(⇔源地址)目录542C-Idempotentfunctions(⇔源地址)tag题意思路AC代码错误次数:1tag*2000+构造+图论+数学。......
  • Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2) D
    D.RestorePermutation题链不难看出我们应该从后往前做我们设t[i]=i*(i-1)/2最后一个i肯定能在t数组直接找到比如我们找到了是3那么要是我们下一个是5我们就要把这个......
  • Codeforces 983 D Arkady and Rectangles 题解
    题目链接挺有意思的数据结构题,题面看着像个板子,其实还是有不少学问的。平面上一堆矩形的题目常见套路就是对\(x\)轴扫描线,\(y\)轴线段树维护,这题也不例外。我们先对坐标......
  • Codeforces Round #769 (Div. 2) B,C
    CodeforcesRound#769(Div.2)B,CBB这道题我在vp的时候一直没有想出来,一直不知道到底怎么写,只是想到和幂有关,wa了一发,后来看了大佬的题解,真是觉得自己太菜了,自愧不如......
  • Codeforces Round #814 (Div. 2)
    A核心思路:这题没什么好说的直接面向样例编程。#include<iostream>#include<cstring>#include<string>#include<vector>#include<math.h>#include<cmath>#inc......
  • 力扣---1768. 交替合并字符串
    给你两个字符串word1和word2。请你从word1开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。返回合......
  • Codeforces Round #586 (Div. 1 + Div. 2) D
    D.AlexandJulian题链很容易发现我们要是两个数互相不构成奇环的话=(a+b)/gcd(a,b)为偶数我们发现如果ab为奇数的时候一定可以并且奇偶一定不同组但是发现24这种又......
  • Educational Codeforces Round 122 (Rated for Div. 2),C,D
    EducationalCodeforcesRound122(RatedforDiv.2),C,DCC这道题就是普通的暴力,但是我在做的过程中第10组数据出现了数据溢出的错误我的错误代码,我在vp的时候没觉得......
  • Codeforces Round #589 (Div. 2) D
    D.CompleteTripartite题链与其他题解不同我首先发现的是没有相连的一定是同一组那么我们直接对于整个数组遍历一遍将与1同组的搞出来要是下一个位置已经有组了我......
  • POJ 1014 Dividing
    POJ1014Dividing题意:多重背包问题,给出若干物品,求是否能分成价值相同的两堆思考:求出总和\(sum\)之后,如果\(sum\)是奇数则一定不可能,然后如果我们能凑出\(sum/......