Codeforces Round #501 (Div. 3)(A-D)(暑假训练8.8)

飞机票

战绩and总结

在这里插入图片描述
又是被兴哥拉一题的一天!!!太牛了ljxyyds!我好菜啊爆哭QAQ

A. Points in Segments

题意:有n条线段和长度m,求在这数轴上从1到m上有哪些不属于任何线段的点
思路①:我敲了发区间合并,调调改改花了十分钟,关于把A题做成难题那种事。。


const int maxn=105;
struct node{
    int l,r;
}mo[maxn],m1[maxn];
bool cmp1(node a,node b)
{
    return a.l<b.l;
}
int main()
{
    int n,m,i,j;
    cin>>n>>m;
    swap(n,m);
    for(i=0;i<m;i++){
        cin>>mo[i].l>>mo[i].r;
    }
    sort(mo,mo+m,cmp1);
    int cnt=0,ll,rr;
    for(i=0;i<m;i++){
        if(i==0){
             m1[cnt].l=mo[i].l;
             m1[cnt++].r=mo[i].r;
        }
        else {
            if(mo[i].l>m1[cnt-1].r){
                 m1[cnt].l=mo[i].l;
                 m1[cnt++].r=mo[i].r;
            }
            else {
                 m1[cnt-1].r=max(m1[cnt-1].r,mo[i].r);
            }
        }
    }
    map<int ,int >mo;
    for(i=0;i<cnt;i++){
        for(j=m1[i].l;j<=m1[i].r;j++)
            mo[j]++;
    }
    int ans=0;
    for(i=1;i<=n;i++){
        if(mo[i]==0) ans++;
    }
    cout<<ans<<endl;
    for(i=1;i<=n;i++){
        if(mo[i]==0) cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}

思路②:其实是树状数组的模板但是数据太小了,所以可以暴力,不过可以树状数组跑(线段树也行啦)
`思路③:兴哥的差分数组,比完告诉我用差分我甚至都没回过神了为什么可以用,其实差分数组里面储存相邻的差,存完之后求个额前缀和,在最后查找没有标记的点即可

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    int b[200]={0},c[200]={0};
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int L,r;
        cin>>L>>r;
        b[L]++;b[r+1]--;
    }
    int  res=0;
    for(int i=1;i<=m;i++)
    {
        b[i]+=b[i-1];
        if(!b[i])
        c[++res]=i;
    }
    cout<<res<<'\n';
    for(int i=1;i<=res;i++)
        cout<<c[i]<<" ";
    cout<<'\n';
    return 0;
}

B. Obtaining the String

题意:
给定两个字符串s1,s2,只能交换s1的相邻元素,为最少需要次可以将s1换成s2.如果没有方法,输出-1.如果有方法,先输出步骤数,然后输出每一次移动的位置。步骤数要在10000以内
思路:两个字符串排序之后要完全相同才有解,有解的情况直接模拟冒泡排序即可,按题意模拟交换

const int maxn=1e5+1000;
int ans[maxn];
int main()
{
    map<char ,int >m1,m2;
    int n,i,j,cnt=0;
    cin>>n;
    string s1,s2;
    cin>>s1>>s2;
    for(i=0;i<s1.length();i++){
        m1[s1[i]]++;
    }
    for(i=0;i<s2.length();i++){
        m2[s2[i]]++;
    }
    bool flag=0;
    for(i=0;i<26;i++){
        char c1='a'+i;
        if(m1[c1]!=m2[c1]) flag=1;
    }
    if(flag==1){
        cout<<-1<<endl;
    }
    else {
        int cnt=0;
        for(i=n-1;i>=0;i--){
            for(j=0;j<n;j++){
                if(s2[i]==s1[j]&&i!=j)
                {
                    while(j!=i&&j<i)
                    {
                        ans[cnt++]=j+1;
                        swap(s1[j],s1[j+1]);
                        j++;
                    }
                    break;
                }
            }
        }
        cout<<cnt<<endl;
        for(i=0;i<cnt;i++)
            cout<<ans[i]<<" ";
    }
    return 0;
}

C. Songs Compression

题意:手机里有n首歌曲,我有一个u盘,想要把歌全部拷到盘里,我可以对音乐进行压缩,使得原本大小为a【i】的歌曲变为b【i】,求最少压缩多少首歌,才能把歌全部装到盘里
思路:十分明显的贪心题,每次压缩都去选择a【i】和b【i 】差距大的
(不开longlong见祖宗)


#define int long long
const int maxn=1e5+100;
struct node{
    int a,b,cha;
}mo[maxn];
bool cmp1(node a,node b)
{
    return a.cha>b.cha;
}
signed main()
{
   int n,m,i,j;
   cin>>n>>m;
   int ans=0,m1=0;
   for(i=0;i<n;i++)
   {
       cin>>mo[i].a>>mo[i].b;
       mo[i].cha=mo[i].a-mo[i].b;
       ans+=mo[i].b; m1+=mo[i].a;
   }
   sort(mo,mo+n,cmp1);
   if(ans<=m)
   {
       int cnt=0,ff=0;
       for(i=0;i<n;i++)
       {
           if(m1<=m)
           {
               ff=1;
               cout<<cnt<<endl;
               break;
           }
           else
           {
               m1-=mo[i].a;
               m1+=mo[i].b;
               cnt++;
           }
       }
       if(ff==0)
            cout<<cnt<<endl;
   }
   else
   {
       cout<<-1<<endl;
   }
}

D. Walking Between Houses

题意:n个房子排成一排,编号从1-n,一开始我在n,我需要移动k次,并且移动的距离刚好是s,输出k次移动到房子的下标
思路:显然每步走s/k格最接近目标,还剩下s%k格,将s%k格分入前面的每一步中
按照兴哥的解释一下为什么最好是走s/k
在这里插入图片描述
这样知道走多少格了那么就每次判断当前位置向前走这么多步行不行,不行就向后(longlong见祖宗*2)


#define int long long
signed main()
{
    int n,k,s,i,j;
    cin>>n>>k>>s;
    if(k>s||(n-1)*k<s){
        scNO;
    }
    else
    {
        scYES;
        int d1=s/k;
        int d2=s/k+1;
        int cnt=s%k;
        int m1=1;
        for(int i=0;i<k;i++){
            if(i<cnt){
                if(m1+d2<=n)
                    cout<<m1+d2<<" ",m1+=d2;
                else
                    cout<<m1-d2<<" ",m1-=d2;
            }
            else {
                if(m1+d1<=n)
                    cout<<m1+d1<<" ",m1+=d1;
                else
                    cout<<m1-d1<<" ",m1-=d1;
            }
        }
        cout<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值