今天2021.10.4,满课。。
1369.C. RationalLee (思维)
题意:
将n个物品分给 m 个人,每个物品有价值
w
i
wi
wi,每个人分到
a
i
ai
ai 个。定义一个人的快乐值为 得到物品的最大价值+最小价值。
问,如何分配使得所有人的快乐值最大?
思路:
一开始想的是:
把物品按价值从大到小排序,然后轮流着发。
但是一个人可能拥有最大价值很高,但是最小价值却很低。
所以,先将最大价值轮流分,然后将剩余的物品一个人一个人补满。
将物品按价值从大到小排序,将所有人按分配个数从小到大排序。
枚举一遍所有人,先铺满一层,然后再遍历依次补齐。
这样,有较大最大价值的人所拥有的最小价值也是尽可能大的。
Code:
const int N = 200010, mod = 1e9+7;
int T, n, m, a[N], b[N];
PII ans[N];
signed main(){
Ios;
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>b[i],ans[i].first=ans[i].second=0;
sort(a+1,a+n+1,greater<int>());
sort(b+1,b+m+1);
int st=m+1;
for(int i=1;i<=m;i++){
if(b[i]==1) ans[i].second=ans[i].first=a[i];
else{st=i;break;}
}
for(int i=st;i<=m;i++) ans[i].first=a[i];
int tm=m;
for(int i=st;i<=m;i++)
{
int t=b[i]-1;
ans[i].second=a[tm+t];
tm+=t;
}
int cnt=0;
for(int i=1;i<=m;i++) cnt+=ans[i].first+ans[i].second;
cout<<cnt<<"\n";
}
return 0;
}
524.B. Han Solo and Lazer Gun
map存储每个点到发射点的斜率。斜率相同可以一发攻击。
昨天 c f cf cf 的B题:
1592.B. Hemose Shopping (思维)
题意:
给出一个长度为n的数列。给出k,数列中的每个位置
i
i
i 都可以和满足
∣
i
−
j
∣
≥
k
|i-j|≥k
∣i−j∣≥k 的位置
j
j
j 互换。
问,该数列是否能够经过若干次交换后,变为不下降数列?
思考:
也就是说,每个位置都可以和k个位置及其之后的位置互换。
那么如果
k
≤
n
/
2
k≤n/2
k≤n/2 的话,数列中的任意两个位置间都可以互换,那么可以变为任意想要的数列;
否则,数列中间一些位置是无法进行交换的。当前数列能变为不降数列,只能中间那些位置原本就是排好的,原本就在他们最终需要在的位置。所以只需要判断中间不能移动的位置是否和排好序的位置对应相同就行了。
中间位置:
[
m
,
n
−
m
+
1
]
[m,n-m+1]
[m,n−m+1]。
Code:
const int N = 200010, mod = 1e9+7;
int T, n, m, a[N],b[N];
int main(){
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
if(m<=n/2){
cout<<"yes\n";continue;
}
sort(b+1,b+n+1);
int flag=0;
for(int i=n-m+1;i<=m;i++){
if(a[i]!=b[i]) flag=1;
}
if(flag) cout<<"no\n";
else cout<<"yes\n";
return 0;
}
明天加油!