bzoj5249 [2018多省省队联测]IIIDX

本文介绍了一种通过线段树优化贪心算法来解决树形结构中寻找最大方案的问题,特别关注了权值重复情况下的处理方法及线段树的应用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转化一下问题变成给定一棵树,一个序列,求父亲的权值小于子树的最大方案。

直接贪心会在有重复权值时出现错误,我们考虑用线段树优化贪心。

将序列从小到大排序,线段树上每个点记录他和他右边当前还可用的权值,注意这里我们并不一定维护的都是正确的,但是我们要保证我们需要用到的限制一定都体现了出来,比如 1 2 5 5 5 5 5 6 7 8 9 K=2,我们放第二个点时,会放到3这个位置,于是我们将1~3区间减7,这时候4~11的权值我们并没有修改,但是需要用到的限制只有前三个点,所以是正确的,之后我们每次在线段树上找到最大的可用位置,然后放到和他权值相同的最左边就可以了。

还要注意我们放一个点时需要先将其父亲的限制去掉。

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#define N 500500
using namespace std;
int n,a[N],fa[N],size[N],pp[N];
double K;
int lazy[N<<2],minn[N<<2];
void pushdown(int rt){
    if(lazy[rt]){
        lazy[rt<<1]+=lazy[rt];minn[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];minn[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void build(int rt,int l,int r){
    if(l==r){minn[rt]=n-l+1;return;}
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
void update(int rt,int l,int r,int x,int y,int z){
    if(x<=l&&r<=y){
        lazy[rt]+=z;minn[rt]+=z;
        return ;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(x<=mid)update(rt<<1,l,mid,x,y,z);
    if(y>mid)update(rt<<1|1,mid+1,r,x,y,z);
    minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
int query(int rt,int l,int r,int x){
    if(l==r){
        if(minn[rt]>=x)return l;
        return l-1;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(minn[rt<<1]>=x)return query(rt<<1|1,mid+1,r,x);
    else return query(rt<<1,l,mid,x);
}
map<int,int> L;
int main(){
    scanf("%d%lf",&n,&K);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
        if(a[i]!=a[i-1])L[a[i]]=i;
    for(int i=1;i<=n;i++)fa[i]=floor(i/K);
    for(int i=n;i;i--){
        size[i]++;
        size[fa[i]]+=size[i];
    }
    build(1,1,n);
    for(int i=1;i<=n;){
        if(fa[i])update(1,1,n,1,pp[fa[i]],size[fa[i]]-1);
        do{
            int x=query(1,1,n,size[i]);
            pp[i]=L[a[x]]++;
            update(1,1,n,1,pp[i],-size[i]);
            i++;
        }while(i<=n&&fa[i]==fa[i-1]);
    }
    for(int i=1;i<=n;i++)printf("%d%c",a[pp[i]],((i==n)?'\n':' '));
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Ren-Ivan/p/8781953.html

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 HttpServletRequestWrapper 是 Java Servlet API 中的一个工具类,位于 javax.servlet.http 包中,用于对 HttpServletRequest 对象进行封装,从而在 Web 应用中实现对 HTTP 请求的拦截、修改或增强等功能。通过继承该类并覆盖相关方法,开发者可以轻松地自定义请求处理逻辑,例如修改请求参数、添加请求头、记录日志等。 参数过滤:在请求到达处理器之前,可以对请求参数进行检查或修改,例如去除 URL 编码、过滤敏感信息或进行安全检查。 请求头操作:可以修改或添加请求头,比如设置自定义的 Content-Type 或添加认证信息。 请求属性扩展:在原始请求的基础上添加自定义属性,供后续处理使用。 日志记录:在处理请求前记录请求信息,如 URL、参数、请求头等,便于调试和监控。 跨域支持:通过添加 CORS 相关的响应头,允许来自不同源的请求。 HttpServletRequestWrapper 通过继承 HttpServletRequest 接口并重写其方法来实现功能。开发者可以在重写的方法中添加自定义逻辑,例如在获取参数时进行过滤,或在读取请求体时进行解密。当调用这些方法时,实际上是调用了包装器中的方法,从而实现了对原始请求的修改或增强。 以下是一个简单的示例,展示如何创建一个用于过滤请求参数的包装器: 在 doFilter 方法中,可以使用 CustomRequestWrapper 包装原始请求: 这样,每当调用 getParameterValues 方法时,都会先经过自定义的过滤逻辑。 HttpServletRequestWrapper 是 Java Web 开发中一个强大的工具,它提供了灵活的扩展性,允许开发者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值