莫队+树状数组 题解【bzoj3289】Mato的文件管理

本文介绍了一种使用莫队算法和树状数组解决区间逆序对问题的方法。通过将问题离散化并分块处理,实现了从O(n^2)到O(n^1.5)的时间复杂度优化。文章详细讲解了代码实现过程,并提供了完整的C++代码。

首先题目意思很简单
就是求每一段区间内的逆序对个数 在我认知中有两种求逆序对的方法 1.归并排序可以求逆序对 2.树状数组求逆序对 修改和查询都是O(logn)的复杂度
本题要不断修改逆序对数据结构只能选择树状数组
然后 就往莫队上去套咯 离线求解 分块 然后按左端点所在的块排序 再按后端点排序
定义一个L,R,不断++,–,update树状数组和更新ans就好了 不过感觉有点抽象 一个小bug调了20多分钟
莫队嘛 反正就是很神奇的暴力 不用多想
注意要离散 因为不知道数据范围
用了莫队就把n^2优化到了n^1.5是不是很神奇呢 其实我也这么觉得 非常神奇
当然这只是最基础的莫队 还有高级一点的莫队要在树上进行 以后有机会再写
大家先看懂这个莫队

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<vector>
#define M 50005
#define ll long long
using namespace std;
struct node{
    int l,r,id;
    int ans;
}Q[M];
int ans,n,m,block[M],A[M],c[M];
int sum(int i){
    int res=0;
    while(i){
        res+=c[i];
        i-=i&-i;
    }
    return res;
}
void update(int i,int x){
    while(i<=n){
        c[i]+=x;
        i+=i&-i;
    }
}
bool cmp(node a,node b){
    if(block[a.l]!=block[b.l])return block[a.l]<block[b.l];
    return a.r<b.r;
}//按块来排序
bool cmp1(node a,node b){
    return a.id<b.id;
}//最后输出的时候还是要按顺序输出的嘛 按id排个序就好了 \(^o^)/~
void Rd(int &res){
    char c;res=0;
    while(c=getchar(),!isdigit(c));
    do res=(res<<1)+(res<<3)+(c^48);
    while(c=getchar(),isdigit(c));
}//读入挂 可以自行忽略
void init(){
    Rd(n);
    int limit=sqrt(n);
    int B[M];
    for(int i=1;i<=n;i++){
        Rd(A[i]);
        B[i]=A[i];
        block[i]=(i-1)/limit+1;
    }
    sort(B+1,B+n+1);//以下几行都是离散操作 sort unique lower_bound
    int k=unique(B+1,B+n+1)-B-1;
    for(int i=1;i<=n;i++)A[i]=lower_bound(B+1,B+k+1,A[i])-B;
    for(int i=1;i<=n;i++){
        update(A[i],1);
        ans+=i-sum(A[i]);//先初始化ans 即逆序对的个数
    }
//  printf("逆序对=%d\n",ans);
    Rd(m);
    for(int i=1;i<=m;i++){
        Rd(Q[i].l);Rd(Q[i].r);
        Q[i].id=i;
    }
    sort(Q+1,Q+m+1,cmp);
}
void solve(){
    int l=1,r=n;//l和r都在最左和最右 然后ans也已经初始化好了 接下来就要开始快乐的暴力环节
    for(int i=1;i<=m;i++){//update更新环节需要自己参悟了 也不能帮太多 这个挺好推的 时刻更新树状数组和ans就好
        while(l<Q[i].l){
            ans-=sum(A[l]-1);
            update(A[l],-1);
            l++;
        }
        while(l>Q[i].l){
            l--;
            update(A[l],1);
            ans+=sum(A[l]-1);
        }
        while(r<Q[i].r){
            r++;
            update(A[r],1);
            ans+=r-l+1-sum(A[r]);
        }
        while(r>Q[i].r){
            ans-=r-l+1-sum(A[r]);
            update(A[r],-1);
            r--;
        }
        Q[i].ans=ans;//最后挪到了要求访问的区间 就把ans记录下来
    }
    sort(Q+1,Q+m+1,cmp1);
    for(int i=1;i<=m;i++)printf("%d\n",Q[i].ans);//输出答案
}
int main(){
    init();
    solve();
    return 0;
}
【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)内容概要:本文介绍了名为《【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)》的研究资源,重点围绕电力系统中连锁故障的传播机制,提出了一种N-k多阶段双层优化模型,并结合故障场景筛选方法提升系统安全性与鲁棒性。该模型通过Matlab代码实现,可用于模拟复杂电力系统在多重故障下的响应特性,支持对关键故障路径的识别与优化决策,适用于高水平科研复现与工程仿真分析。文中还列举了大量相关技术方向的配套资源,涵盖智能优化算法、电力系统管理、机器学习、路径规划等多个领域,并提供了网盘链接以便获取完整代码与资料。; 适合人群:具备电力系统、优化理论及Matlab编程基础的研究生、科研人员及从事能源系统安全分析的工程技术人员,尤其适合致力于高水平论文(如EI/SCI)复现与创新的研究者。; 使用场景及目标:①复现顶级期刊关于N-k故障与连锁传播的优化模型;②开展电力系统韧性评估、故障传播分析与多阶段防御策略设计;③结合YALMIP等工具进行双层优化建模与场景筛选算法开发;④支撑科研项目、学位论文或学术成果转化。; 阅读建议:建议读者按照文档提供的目录顺序系统学习,优先掌握双层优化与场景筛选的核心思想,结合网盘中的Matlab代码进行调试与实验,同时参考文中提及的智能算法与电力系统建模范例,深化对复杂电力系统建模与优化的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值