iwtgm-16
A.
层取,因为它的高度只有2e5,我把每个高度的方格个数记录下来
最后从高到低跑一遍,大于k的ans++
有几个点:
顺序无关紧要,所以先从小到大排个序
从右往左,若前一个与当前的高度相同就continue,直到高度不相同
有一个变量now,记录的是当前高度
把当前高度-1的方格个数就是n-i+1
因为我们是一层一层递减的,且是排好序的,所以当前和当前后面这个高度一定有方格
只要前一个与当前高度不一样,now就不断记录个数然后--
高度数组h[0]的高度是0,一定与其他高度不同
然后要注意的是在最后统计答案时
若tmp+当前高度的个数>k,那么ans++,tmp=当前高度的个数
若==k,tmp=0
ll n,k;
ll h[N];
ll cnt[N];
void solve()
{
cin>>n>>k;
ll now=-1,ma;
ll mi=inf;
for(int i=1;i<=n;i++){
cin>>h[i];
if(h[i]>now)now=h[i];
if(h[i]<mi)mi=h[i];
}
ma=now-1;
sort(h+1,h+1+n);
bool f=false;
for(int i=n;i>=1;i--){
if(h[i-1]==now)continue;
while(h[i-1]!=now) {
cnt[now - 1] = n - i + 1;
//cout<<"now-1="<<now-1<<' '<<"num="<<n-i+1<<endl;
now--;
if(now==mi){
f=true;break;
}
}
if(f==true)break;
}
ll tmp=0,ans=0;
for(int i=ma;i>=mi;i--){
if(tmp+cnt[i]<k)tmp+=cnt[i];
else if(tmp+cnt[i]==k){
ans++;tmp=0;
}
else{
ans++;
tmp=cnt[i];
}
if(i==mi&&tmp)ans++;
}
cout<<ans;
}
B.
设矩形两边分别为a,b
那么就是求4(a+b)^2/(ab)最小
因为(a+b)^2>=0,把括号展开、移项
得到a2+b2>=2ab,当ab时等号成立
可得当ab的时候也就是正方形的时候是最小的
然后就是让a尽可能接近b,即b/a尽可能小(b>a)
对边长计数,>=4的就输出它
记录所有>=2的边长,看相邻两个谁的b/a最小就输出哪两条
提一嘴错误思路:
分子是平方级的,想着让a,b尽可能小整个分式就能小
这样不无道理但并不全对
#define int long long
ll cnt[N];
vector<ll>v;
void solve()
{
memset(cnt,0,sizeof(cnt));v.clear();
int n;cin>>n;
int success=-1;
for(int i=1,x;i<=n;i++){
cin>>x;cnt[x]++;
if(cnt[x]==2)v.push_back(x);
if(cnt[x]==4)success=x;
}
if(success!=-1){
for(int i=1;i<=4;i++){
cout<<success<<' ';
}
cout<<endl;return ;
}
int ans1,ans2;
long double mi=inf;
long double tmp;
sort(v.begin(),v.end());
for(int i=1;i<v.size();i++){
tmp=v[i]*1.0/v[i-1];
if(tmp<mi){
mi=tmp;
ans1=v[i-1];ans2=v[i];
}
}
for(int i=1;i<=2;i++){
cout<<ans1<<' '<<ans2<<' ';
}
cout<<endl;
}
C.
这题自己想了挺多,有两个维度,一个是同种编号的数量,一个是最大读的信息数
并不好对一维排序然后处理另一维
首先这题是求期望,样例给的思路是把所有情况满足条件的人数求个总和再除以钉住的信息数
但这样显然数据量大且不好处理
于是打算根据期望的意义另开辟一条思路
举个例子,有10条信息供你选择,你最多读3条,那么你满足条件的期望就是3/10,跟总和/钉住信息数等价,至此简化了题意
于是我对于每个编号圈了一个集合,枚举钉住信息数量,(必选当前这条信息)我可以得到多大的期望
因为每个人最大阅读信息数量范围只有20,当我钉住信息数量大于20时,那么每条有效期望都是1/钉住信息数
差别只有每个编号集合元素的数量
把每个编号的答案放进答案数组里并按从大到小排序
得到答案:
选一条钉住,就是前一条
两条钉住,就是前两条
...
然后从21枚举到n,逐一比较答案
int n;
struct node{
int cnt;
vector<int>v;
};
map<int,node>mp;//编号,k集
int cnt[25];
vector<pair<long double,int>>ans[25];
bool cmp(pair<long double,int> x,pair<long double,int>y){
return x.first>y.first;
}
int a1,a2;
vector<pair<int,int>>more;
bool cmp1(pair<int,int>x,pair<int,int>y){
return x.first>y.first;
}
void solve()
{
cin>>n;
for(int i=0,id,k;i<n;i++){
cin>>id>>k;
mp[id].v.push_back(k);
mp[id].cnt++;
}
for(auto tmp:mp){
more.push_back({tmp.second.cnt,tmp.first});
memset(cnt,0,sizeof(cnt));
for(int i=0;i<tmp.second.v.size();i++){
cnt[tmp.second.v[i]]++;
}
for(int i=1;i<=20;i++){
long double tm=0;
for(int j=1;j<=20;j++){
if(j*1.0/i>1)tm+=1*cnt[j];
else tm+=j*1.0/i*cnt[j];
}
ans[i].push_back({tm,tmp.first});
}
}
for(int i=1;i<=20;i++){
sort(ans[i].begin(),ans[i].end(),cmp);
}
long double tmp=-1;
for(int i=1;i<=20;i++){
long double tt=0;
for(int j=0;j<i&&j<ans[i].size();j++){
tt+=ans[i][j].first;
}
//cout<<"tt="<<tt<<endl;
if(tt>tmp){
tmp=tt;
a1=i;
}
}
sort(more.begin(),more.end(),cmp1);
int sum=0;
for(int i=0;i<more.size();i++){
if(i<20){
sum+=more[i].first;continue;
}
sum+=more[i].first;
long double tt=sum*1.0/(i+1);
// cout<<"a2tt="<<tt<<endl;
if(tt>tmp){
a2=i+1;tmp=tt;
}
}
if(a2){
cout<<a2<<endl;
for(int i=0;i<a2;i++){
cout<<more[i].second<<' ';
}
}
else {
int size=ans[a1].size();
int a11=min(a1,size);
cout<<a11<<endl;
for(int i=0;i<ans[a1].size()&&i<a1;i++){
cout<<ans[a1][i].second<<' ';
}
}
}
好,上面思路有误,进行紧急更正
事实上只要枚举前20个钉住信息就好了
因为信息数>20时,分母变大,所有期望都会下降
又因为我们已经进行了排序操作,贡献大的都排在前面,后面的贡献不会比前面好又会下降大家的期望,那么一定不会更优
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现