目录
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;
}