AT5693 [AGC041B] Voting Judges(尺取 前缀和 二分)

17 篇文章 0 订阅

https://www.luogu.com.cn/problem/AT5693

题意:

给出一个数组,有m次操作,每次选中V个数+1,然后选中最大的P个数(相同的数随意排序),问多少个位置的数可能被选中

解析:

排序后,考虑第 i i i个数是否可能被选中:

  • 首先a[i]这个数每次都会被选中,所以要求操作后大于 a [ i ] + m a[i]+m a[i]+m的数少于 P P P个。
  • 也就是说对于大的数,尽可能分配少一点。
  • 小于等于 a [ i ] a[i] a[i]的可以每次全部选。
  • 大于 a [ i ] + m a[i]+m a[i]+m的数不管分不分都大于 a [ i ] + m a[i]+m a[i]+m,所以也是每次选。
  • 所以考虑的区间要求 a [ i ] < a [ j ] ≤ a [ i ] + m a[i]< a[j]\leq a[i]+m a[i]<a[j]a[i]+m,这个用尺取法维护
  • 区间内二分得到至少多少个数加完后大于 a [ i ] + m a[i]+m a[i]+m,这些数默认分配 m m m
    • 区间内大于等于 a [ i ] + m a[i]+m a[i]+m的可以分配 a [ i ] + m − a [ j ] a[i]+m-a[j] a[i]+ma[j],这个用前缀和直接得到

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-10-07-12.07.54
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define LD long double
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

LL n=rd,m=rd,v=rd,p=rd;
LL a[maxn];
LL sum[maxn];
inline LL segsum(int l,int r){return sum[r]-(l==1?0:sum[l-1]);}

int main(){
    rep(i,1,n)a[i]=rd;
    sort(a+1,a+1+n);
    rep(i,1,n)sum[i]=sum[i-1]+a[i];
    int mx=a[n];
    int l=1,r=0;
    int ans=0;
    rep(i,1,n){
        if(a[i]==mx){ans++;continue;}
        /// a[j]>a[i]
        while(a[l]==a[i])l++;
        /// a[j]<=a[i]+m
        while(r<n&&a[r+1]<=a[i]+m)r++;
        LL res=v-(l-1);
        LL g=n-r;
        res-=g;
        /// [l,r]
        if(l<=r&&res>0){
            /// 二分区间内后面_ans个数直接+m
            int L=0,R=r-l+1,_ans=-1;
            while(L<=R){
                int mid=L+R>>1;
                LL left=1ll*(r-l+1-mid)*(a[i]+m)-segsum(l,r-mid);
                if((res-mid)*m<=left){
                    _ans=mid;
                    R=mid-1;
                }
                else{
                    L=mid+1;
                }
            }
            g+=_ans;
        }
        if(g<p)ans++;
    }
    printf("%d\n",ans);
    return 0;
}

/*_________________________________________________________end*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
package com.example.ibm; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import com.google.gson.Gson; import java.io.IOException; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity { private EditText etHeight; private EditText etWeight; private Button btnCalculate; private TextView tvResult; private OkHttpClient client; private Gson gson; private static final String API_KEY = "d889e63ef7ad041b837dcc1b3ebc5a2b"; private static final String API_URL = "http://apis.juhe.cn/fapig/calculator/weight"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etHeight = findViewById(R.id.et_height); etWeight = findViewById(R.id.et_weight); btnCalculate = findViewById(R.id.btn_calculate); tvResult = findViewById(R.id.tv_result); client = new OkHttpClient(); gson = new Gson(); btnCalculate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String height = etHeight.getText().toString(); String weight = etWeight.getText().toString(); if (height.isEmpty() || weight.isEmpty()) { tvResult.setText("请输入身高和体重"); return; } float h = Float.parseFloat(height); float w = Float.parseFloat(weight); if (h <= 0 || w <= 0) { tvResult.setText("身高和体重必须大于0"); return; } calculateBMI(h, w); } }); }
最新发布
06-09

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值