【JZOJ 3854】分组

精灵社区分组算法
针对一个精灵社区,设计一种算法来解决如何最大化包含特定成员的小组人数问题,同时确保队长地位最高且年龄差距不超过限定值。

Description

Bsny所在的精灵社区有n个居民,每个居民有一定的地位和年龄,ri表示第i个人的地位,ai表示第i个人的年龄。
最近社区里要举行活动,要求几个人分成一个小组,小组中必须要有一个队长,要成为队长有这样的条件:
1、队长在小组中的地位应该是最高的(可以并列第一);
2、小组中其他成员的年龄和队长的年龄差距不能超过K。
有些人想和自己亲密的人组在同一个小组,同时希望所在的小组人越多越好。比如x和y想在同一个小组,同时希望它们所在的小组人越多越好,当然,它们也必须选一个符合上述要求的队长,那么问你,要同时包含x和y的小组,最多可以组多少人?

Solution

先把每个人按地位排序,这样就可以预处理出每个人做组长可以领导多少人,(这里我用了树状数组)
再把输入的问题也按两个人中地位最大的排序,离线处理,
对于每个人可以确认一个年龄区间,要保证组长一定在这个年龄范围内,
用一个指针指向每一组人,按全部人的地位从大到小循环,看一下指向的组两人的最大地位是否大于当前的人,是则结算当前的人答案,指针后移,最后加上当前人的影响,(鄙人的语文辣鸡,大家可以看看代码理解一下)
这个可以用线段树,

复杂度:O(nlog(n))

Code

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define NX(x) ((x)&(-(x)))
using namespace std;
const int N = 1e5+500;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m,m1;
int zx[N],ans[N];
struct qqww
{
    int rk,a,i,f,zx;
}a[N];
int A[N];
int F[N];
struct qwqw
{
    int x,y,i;
}sc[N];
int b[4*N];
bool PX(qqww q,qqww w){return q.rk<w.rk || q.rk==w.rk&&q.a<w.a;}
bool PPX(qwqw q,qwqw w){return a[q.x].rk<a[w.x].rk;}
int SUM(int q)
{
    int ans=0;
    for(;q>0;q-=NX(q))ans+=F[q];
    return ans;
}
void ADD(int q){for(;q<=m1;q+=NX(q))F[q]++;}
int find(int l,int r,int e,int l1,int r1)
{
    if(l==l1&&r==r1)return b[e];
    int t=(l+r)>>1;
    if(r1<=t)return find(l,t,e*2,l1,r1);
        else if(t<l1)return find(t+1,r,e*2+1,l1,r1);
            else return max(find(l,t,e*2,l1,t),find(t+1,r,e*2+1,t+1,r1));
}
void change(int l,int r,int e,int l1,int l2)
{
    if(l==r){b[e]=max(b[e],l2);return;}
    int t=(l+r)>>1;
    if(l1<=t)change(l,t,e*2,l1,l2);
        else change(t+1,r,e*2+1,l1,l2);
    b[e]=max(b[e*2],b[e*2+1]);
}
int main()
{
    int q,w,_;
    read(n),read(m);
    fo(i,1,n)read(a[i].rk),a[i].i=i;
    fo(i,1,n)A[i]=read(a[i].a);
    sort(a+1,a+1+n,PX);
    fo(i,1,n)zx[a[i].i]=i;
    sort(A+1,A+1+n);
    m1=1;
    fo(i,2,n)if(A[i]!=A[i-1])A[++m1]=A[i];
    int t=1;
    fo(i,1,n)
    {

        a[i].zx=lower_bound(A+1,A+1+m1,a[i].a)-A;
        ADD(a[i].zx);
        if(a[i].rk!=a[i+1].rk)
        while(t<=i)
        {
            q=lower_bound(A+1,A+1+m1,a[t].a-m)-A;
            w=upper_bound(A+1,A+1+m1,a[t].a+m)-A-1;
            a[t].f=SUM(w)-SUM(q-1),t++;
        }
    }
    // fo(i,1,n)printf("%d ",a[i].f);printf("\n");
    read(_);
    int __=_;
    fo(i,1,_)
    {
        read(q),read(w);q=zx[q],w=zx[w];
        if(a[q].rk<a[w].rk)swap(q,w);
        sc[i].x=q,sc[i].y=w;sc[i].i=i;
    }
    sort(sc+1,sc+1+_,PPX);
    fod(i,n,0)
    {
        for(;a[i].rk<a[sc[_].x].rk;_--)
        {
            if(a[sc[_].x].a<a[sc[_].y].a)swap(sc[_].x,sc[_].y);
            q=lower_bound(A+1,A+1+m1,a[sc[_].x].a-m)-A;q=max(1,q);
            w=upper_bound(A+1,A+1+m1,a[sc[_].y].a+m)-A-1;
            if(q<=w)ans[sc[_].i]=find(1,n,1,q,w);
        }
        change(1,n,1,a[i].zx,a[i].f);
    }
    fo(i,1,__)if(ans[i])printf("%d\n",ans[i]);else printf("-1\n");
    return 0;
}
【直流微电网】径向直流微电网的状态空间建模与线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模与线性化方法,重点提出了一种基于耦合DC-DC变换器状态空间平均模型的建模策略。该方法通过对系统中多个相互耦合的DC-DC变换器进行统一建模,构建出整个微电网的集中状态空间模型,并在此基础上实施线性化处理,便于后续的小信号分析与稳定性研究。文中详细阐述了建模过程中的关键步骤,包括电路拓扑分析、状态变量选取、平均化处理以及雅可比矩阵的推导,最终通过Matlab代码实现模型仿真验证,展示了该方法在动态响应分析控制器设计中的有效性。; 适合人群:具备电力电子、自动控制理论基础,熟悉Matlab/Simulink仿真工具,从事微电网、新能源系统建模与控制研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网中多变换器系统的统一建模方法;②理解状态空间平均法在非线性电力电子系统中的应用;③实现系统线性化并用于稳定性分析与控制器设计;④通过Matlab代码复现扩展模型,服务于科研仿真与教学实践。; 阅读建议:建议读者结合Matlab代码逐步理解建模流程,重点关注状态变量的选择与平均化处理的数学推导,同时可尝试修改系统参数或拓扑结构以加深对模型通用性适应性的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值