首页 > 其他分享 >CF1945F Kirill and Mushrooms

CF1945F Kirill and Mushrooms

时间:2024-09-07 11:46:31浏览次数:9  
标签:橡树 CF1945F 基里尔 int Mushrooms Kirill 灵药 蘑菇 魔力

题意

营地里的人一睡着,基里尔就偷偷溜出帐篷,去智者橡树那里采蘑菇。

众所周知,橡树下生长着 \(n\) 种蘑菇,每种蘑菇都有 \(v_i\) 的魔力。基里尔非常想用这些蘑菇制作一种魔力最大的灵药。

灵药的强度等于其中蘑菇的数量与这些蘑菇中最小魔力的乘积。为了配制灵药,基里尔将依次采摘生长在橡树下的蘑菇。基里尔可以按照任何顺序采集蘑菇。

然而,事情并非如此简单。智慧橡树告诉基里尔从 \(1\) 到 \(n\) 的数字 \(p\) 的排列组合。如果基里尔只采摘 \(k\) 蘑菇,那么所有指数为 \(p_1, p_2, \dots, p_{k - 1}\) 的蘑菇的魔力就会变成 \(0\) 。基里尔不会使用魔力为零的蘑菇来配制灵药。

你的任务是帮助基里尔采集蘑菇,使他能够酿造出最大魔力的灵药。不过,基里尔有点害怕在橡树附近逗留太久,所以在所有适合采集蘑菇的选项中,他要求您找到蘑菇数量最少的那个。

长度为 \(n\) 的排列是由 \(n\) 个不同的整数组成的数组,这些整数的顺序从 \(1\) 到 \(n\) 。例如, \([2,3,1,5,4]\) 是一个排列,但 \([1,2,2]\) 不是排列( \(2\) 在数组中出现两次), \([1,3,4]\) 也不是排列( \(n=3\) ,但 \(4\) 在数组中出现)。

思路

考虑枚举摘 \(k\) 个蘑菇,然后就可以获得哪些蘑菇会归 \(0\) , 则答案贪心的想即选前 \(k\) 个蘑菇
则最小值为当前序列第 \(k\) 大

支持修改且可以动态维护第 \(k\) 大的显然是权值线段树

代码

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int a[N];
int b[N];
int v[N];
struct node
{
    int l,r;
    int sum;
}tr[N<<2];
void pushup(int id){tr[id].sum=tr[id<<1].sum+tr[id<<1|1].sum;}
void build(int id,int l,int r)
{
    tr[id]={l,r};
    if(l==r)
    {
        return;
    }
    int mid=(l+r)/2;
    build(id<<1,l,mid);
    build(id<<1|1,mid+1,r);
}
void change(int id,int x,int v)
{
    if(tr[id].l==tr[id].r)
    {
        tr[id].sum+=v;
        return;
    }
    int mid=(tr[id].l+tr[id].r)/2;
    if(x<=mid) change(id<<1,x,v);
    else change(id<<1|1,x,v);
    pushup(id);
}
int find(int id,int k)
{
    if(tr[id].l==tr[id].r)
    {
        return tr[id].l;
    }
    if(k<=tr[id<<1|1].sum) return find(id<<1|1,k);
    else return find(id<<1,k-tr[id<<1|1].sum);
}
int main()
{
    int _;
    cin>>_;
    while(_--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+1+n);
        int m=unique(b+1,b+1+n)-b-1;
        build(1,1,m);
        for(int i=1;i<=n;i++)
        {
            a[i]=lower_bound(b+1,b+1+m,a[i])-b;
            change(1,a[i],1);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v[i]);
        }
        long long ans=b[m];
        int id=1;
        for(int i=2;i<=n;i++)
        {
            if(n-i+1<i) break;
            change(1,a[v[i-1]],-1);
            long long cnt=1LL*b[find(1,i)]*i;
            if(cnt>ans)
            {
                ans=cnt;
                id=i;
            }
        }
        cout<<ans<<" "<<id<<"\n";
    }
}

标签:橡树,CF1945F,基里尔,int,Mushrooms,Kirill,灵药,蘑菇,魔力
From: https://www.cnblogs.com/Oistream/p/18401503

相关文章

  • qoj1138 Counting Mushrooms
    交互题。有一个隐藏的01序列\(a\),你只知道\(a\)的长度,并记为\(n\)。保证\(a_1=0\)。你可以执行以下操作:询问一个序列\(b\),满足两两不同且长度在\([2,1000]\)之间。交互库会返回\(\sum[a(b_i)\not=a(b_{i+1})]\)。请在\(226\)次操作内求出\(a\)中\(0\)......
  • Kirill and Mushrooms
    原题链接题解1.选k个数,就会有k-1个数没法选。我们可以倒着来,每少选一个数,就会多一个数可以选,添加总比删除简单2.最小的那个数,也就是第k小的数,因此我们可以维护一个大小为k的优先队列,最小值就是队首元素code#definelllonglong#include<bits/stdc++.h>usingnamespacest......
  • CodeForces1741G-Kirill and Company题解
    \(\large\text{CodeForces1741G-KirillandCompany题解}\)题面传送门(有翻译(由黄巨佬提供))思路预处理因为\(k\)很小,所以可以先bfs预处理出家在\(i(2\lei\len)\)的人能捎带上哪些集合的人,在表示集合时用一个\(0\)到\(2^k-1\)的整数\(j\)表示,若\(j\)在二进质下的......
  • CF 894E(Ralph and Mushrooms-Tarjen)
    给一个有向图,每条边有边权w,第k次经过一条边获得max(0,w−1−2−..−(k−1)),问最大获得权值。显然一个点强联通分量里的点可以一次取走,对原图缩点,跑DAG.#include<iostre......