A- Make 10
传送门
题意
你有三种棍子,长度分别为2,3,4;每一种有A i个。你需要尽可能多的用这三种棍子组成长度为10的棍子,并输出能组成多少根。
思路
贪心 我们可以发现长度为3的棍子必须两两出现,我们可以将其组成一个长度为6的。然后我们贪心的优先选取长度最长的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int T;
cin>>T;
while(T--){
ll a,b,c;
cin>>a>>c>>b;
ll ans=0,t=0;
c/=2;
if(b&&c){
t=min(b,c);
b-=t;c-=t;
ans+=t;
}
if(c&&a>=2){
t=min(c,a/2);
a-=t*2;c-=t;
ans+=t;
}
if(b>=2&&a){
t=min(a,b/2);
a-=t;b-=t*2;
ans+=t;
}
if(b&&a>=3){
t=min(b,a/3);
a-=t*3;b-=t;
ans+=t;
}
if(a){
ans+=a/5;
}
cout<<ans<<"\n";
}
return 0;
}
B - Cross-free Matching
LIS题,对ai排序后求bi的LIS。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=2e5+5;
PII p[maxn];
int dp[maxn],a[maxn];
bool cmp(PII x,PII y){return x.first==y.first ? x.second>y.second:x.first<y.first ;}//若second顺序反过来则会记录1-2,1-3导致错误
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d",&p[i].first,&p[i].second);
sort(p+1,p+m+1,cmp);
int len=1;
memset(dp,0x3f,sizeof dp);
dp[1]=p[1].second;
for(int i=2;i<=m;i++){
if(p[i].second>dp[len])
dp[++len]=p[i].second;
else{
int pos=lower_bound(dp+1,dp+1+n,p[i].second)-dp;
dp[pos]=p[i].second;
}
}
cout<<len;
return 0;
}