浙大第十九届校赛

目录

A、Thanks, TuSimple!

E、Potion

G、Postman

J、Extended Twin Composite Number


A、Thanks, TuSimple!

题目链接http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5979

 

题意:有n个男生 m个女生。 这些人要在一起配对跳舞。但是男生和女生都有对舞伴的要求。输入数据第一行是n个男生的身高, 第二行是m个女生的身高,第三行是男生对舞伴身高的要求,第四行是女生对舞伴身高的要求。(1代表舞伴必须比自己高,0表示舞伴必须比自己矮。) 要你求出最多有多少种配对方式。

 

分析:做法有很多种,其中我感觉比较容易想的就是二分。思想就是男生去匹配女生。用两个集合存储女生的身高,然后分别找符合要求要求的即可。

#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<stdio.h>
#include<cstring>
#include<stdlib.h>
#include<sstream>
#include<set>
#define maxn 1000050
using namespace std;
struct node
{
    int num;
    int p;

};
struct rule
{
    bool operator()(const node & t1,const node & t2)
    {
        return t1.num<t2.num;
    }
};
node a[maxn];
set<int> s1;
set<int> s2;
int b[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        s1.clear();
        s2.clear();
        memset(b,0,sizeof(b));
        int x;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) scanf("%d",&a[i].num);
        for(int i=0;i<m;i++) scanf("%d",&b[i]);
        for(int i=0;i<n;i++) scanf("%d",&a[i].p);
        for(int i=0;i<m;i++)
        {
            scanf("%d",&x);
            if(x==1)
                s1.insert(b[i]);
            else
                s2.insert(b[i]);
        }
        sort(a,a+n,rule());
        int ans=0;
        set<int>::iterator it;
        for(int i=0;i<n;i++)
        {
            if(a[i].p==0)
            {
                it=s1.begin();
                if(a[i].num>*it)
                {
                    ans++;
                    s1.erase(it);
                }
            }
            else
            {
                it=s2.upper_bound(a[i].num);
                if(it!=s2.end())
                {
                    if(*it>a[i].num)
                    {
                        ans++;
                        s2.erase(it);
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

 第二种方法,更巧妙。

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <stack>
#include <utility>
#include <set>
#include <vector>
#include <map>
#define mod 1e9+7
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;

const int maxn = 1e5;

struct node
{
    ll h,p;
    int id;
    bool operator < (const node &a) const{
        return h<a.h;
    }
}num[maxn*2+5];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&num[i].h),num[i].id=1;
        for(int j=n+1;j<=m+n;j++) scanf("%lld",&num[j].h),num[j].id=0;
        for(int i=1;i<=n;i++) scanf("%lld",&num[i].p),num[i].id=1;
        for(int j=n+1;j<=m+n;j++) scanf("%lld",&num[j].p),num[j].id=0;
        sort(num+1,num+1+n+m);
        int maleneed=0,famaleneed=0;
        int ans=0;
        for(int i=1;i<=m+n;i++){
            if(num[i].id==1){
                if(num[i].p==1) maleneed++;
                else if(famaleneed>0) ans++,famaleneed--;
            }else{
                if(num[i].p==1) famaleneed++;
                else if(maleneed>0) ans++,maleneed--;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
 }

下面是我比赛的代码 (有错误不能AC)

 

#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<stdio.h>
#include<cstring>
#include<stdlib.h>
#include<sstream>
#include<set>
using namespace std;
#define maxn 1000050
struct node
{
    int sex;
    int num;
};
struct rule
{
    bool operator()(const node &t1,const node &t2)
    {
        return t1.num<t2.num;
    }
};
int a[maxn];
int a2[maxn];
int b[maxn];
int b2[maxn];
node x[maxn];
multiset<node,rule> se;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        se.clear();
        int n,m;
        scanf("%d%d",&n,&m);
        memset(x,0,sizeof(struct node)*maxn);
        memset(a,0,sizeof(a));
        memset(a2,0,sizeof(a2));
        memset(b,0,sizeof(b));
        memset(b2,0,sizeof(b2));
        for(int i=0;i<n;i++) scanf("%d",&a[i]);//身高
        for(int i=0;i<m;i++) scanf("%d",&b[i]);
        for(int i=0;i<n;i++) scanf("%d",&a2[i]);//要求
        for(int i=0;i<n;i++) scanf("%d",&b2[i]);
        int k=0;
        int j=0;
        node s;
        for(int i=0;i<n;i++)
        {
            if(a2[i]==1)
                {x[k].num=a2[i]+a[i];x[k].sex=1;k++;}//男
            else
                {s.num=a[i];s.sex=1;se.insert(s);}
        }
        for(int i=0;i<m;i++)
        {
            if(b2[i]==1)
                {x[k].num=b2[i]+b[i];x[k].sex=0;k++;}
            else
                {s.num=b[i];s.sex=0;se.insert(s);}
        }
        sort(x,x+k,rule());
        j=se.size();
        int ans=0;
        int aa;
        multiset<node,rule>::iterator p;
        multiset<node,rule>::iterator bb;
        for(int i=0;i<k;i++)
        {
            int number=x[i].num;
            node m;
            m.num=number;
            aa=0;
            if(x[i].sex==1)//男
            {
               m.sex=0;
               p=se.begin();
               while(1)
               {
                   p=se.lower_bound(se,se+j,m,rule());
                   aa=p-se.begin();
                   if((*p).sex!=0) continue;
                   else break;
                   if(aa==j)
                    break;
               }
               if(aa<j)
               {
                   ans++;
                   bb=p;
                   se.erase(bb);
               }
            }
            else//女
            {
                m.sex=1;
                while((*p).sex!=1)
                {
                    p=se.lower_bound(se.begin()+aa,se.end(),m,rule());
                    int l=p-se.begin();
                    aa=l+1;
                    if((*p).sex!=1) continue;
                    else break;
                    if(aa==j)
                        break;
                }
                if(aa<j)
                {
                    ans++;
                    bb=p;
                    se.erase(bb);
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

比赛之后我同学他们都是用贪心做的,但是我想的是用二分,感觉更简单一点,也不会超时,但是比赛的时候在lower_bound卡住了。后来改了半天才知道自己lower_bound 第三个参数的类型写错了。。。服了 但是后来改了半天发现还是不能过,我知道我错在了哪,但是改了几遍用了几种方式都不行 这是最后改出来的代码,也不能过 就放在这以后留着自己再看吧。

 

E、Potion

题目链接http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5983

 

分析:题目的大概意思就是要制作药水,但是材料不够,有一种方法就是可以通过高等级的药水分解得到低等级的。问是否能制作出药水。

这题就一个枚举就行了 总结一下自己WA的原因就是没用longlong !!!   我以为10^9 用int可以   以后长个记性吧。

 

AC代码

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cstring>
using namespace std;
typedef long long ll;
int main()
{
//    freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        ll a[150];
        ll b[150];
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%lld",&b[i]);
        ll num=0;
        if(b[n]-a[n]<0)
            cout<<"No"<<endl;
        else
        {
            num=b[n]-a[n];
            int flag=1;
            for(int i=n-1;i>=1;i--)
            {
                if(a[i]-b[i]<=0)
                    num+=(b[i]-a[i]);
                else
                    num-=(a[i]-b[i]);
                if(num<0)
                {
                    flag=0;
                    break;
                }
            }
            if(flag==1)
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}

 

G、Postman

题目链接http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5985

 

题意:一个人要送n封邮件,但是一次最多拿k,件邮局初始的坐标是x=0。给出n个坐标 问最这个人送完邮件所走的最短距离。题目要求送完邮件最后的坐标不用在x=0处。

 

分析:虽然题目要求最后送完邮件不用回到邮局(x=0处)。但是我们假设最后回到x=0处,这样问题更好想一点。那么这样送邮件的话,根据我们正常的思路,肯定是先送远处的,最后再送近处的。所以开两个数组分别枚举即可求出距离,最后再减去最远处的距离就是我们的答案。

 

AC代码

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cstring>
typedef long long ll;
using namespace std;
#define maxn 100050
ll s1[maxn];
ll s2[maxn];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        memset(s1,0,sizeof(s1));
        memset(s2,0,sizeof(s2));
        ll num1=0;
        ll num2=0;
        ll x;
        for(int i=0; i<n; i++)
        {
            scanf("%lld",&x);
            if(x<0)
                s1[num1++]=abs(x);
            else if(x>0)
                s2[num2++]=x;
        }
        sort(s1,s1+num1);
        sort(s2,s2+num2);
        ll maxlength;
        ll ans=0;
        for(int i=num2-1;i>=0;i-=k)
            ans+=2*s2[i];
        for(int i=num1-1;i>=0;i-=k)
            ans+=2*s1[i];
        maxlength=max(s1[num1-1],s2[num2-1]);
        printf("%lld\n",ans-maxlength);
    }
    return 0;
}

这题自己做的时候思路已经想到了 代码也实现了 但是一开始WA了好几遍。原因是我用的vector数组,感觉自己给弄复杂了,因为当左边或者右边存在没有坐标的时候,那么求最大距离maxlength就不好求了 就要分情况讨论。而用数组一开始用memset置0则会避免这一情况。而且for循环枚举的也不用判断。而且有一种特殊情况我没考虑到那就是 左右边都为0的情况!!一定要记得赋初值啊。

下面是我之前写的代码 (能AC)

#include<iostream>
#include<vector>
#include<algorithm>
typedef long long ll;
using namespace std;

vector<ll> s1;
vector<ll> s2;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        s1.clear();
        s2.clear();
        int n,k;
        scanf("%d%d",&n,&k);
        ll x;
        for(int i=0; i<n; i++)
        {
            scanf("%lld",&x);
            if(x<0)
                s1.push_back(abs(x));
            else if(x>0)
                s2.push_back(x);
        }
        sort(s1.begin(),s1.end());
        sort(s2.begin(),s2.end());
        ll num1=s1.size();//左边的个数
        ll num2=s2.size();//右边的个数
        ll maxlength=0;
        ll ans=0;
        if(num1&&num2)
        {
            maxlength=max(s1[num1-1],s2[num2-1]);

            for(int i=num2-1;i>=0;i-=k)
                ans+=2*s2[i];
            for(int i=num1-1;i>=0;i-=k)
                ans+=2*s1[i];
        }
        else if(num2)
        {
            maxlength=s2[num2-1];

            for(int i=num2-1;i>=0;i-=k)
                ans+=2*s2[i];
        }
        else if(num1)
        {
            maxlength=s1[num1-1];

            for(int i=num1-1;i>=0;i-=k)
                ans+=2*s1[i];
        }
        printf("%lld\n",ans-maxlength);
    }
    return 0;
}

 

 

J、Extended Twin Composite Number

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5988

 

这题输出要求太简单了  输出任意一组数据就行 ,所以直接乘8 乘9就可以过了。

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        long long n;
        long long x,y;
        scanf("%lld",&n);
        x=8*n;
        y=9*n;
        printf("%lld %lld\n",x,y);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值