倍增法和ST算法 个人学习笔记&代码

倍增法

P4155 国旗计划

cpp 复制代码
#include<bits/stdc++.h>
#define endl '\n'
#define forr(i,l,r) for(int i=l;i<=r;i++)
#define reforr(i,l,r) for(int i=r;i>=l;i--)
#define int long long
using namespace std;
const int N=4e5+10,M=20;
struct wa
{
    int id,l,r;
}a[N*2];
int n,m,nt;
int go[N][M],res[N];
void init(){
    int nxt=1;
    forr(i,1,nt){
        while (nxt<=nt&&a[nxt].l<=a[i].r)//找下一个最优区间
        {
            nxt++;
        }
        go[i][0]=nxt-1;//2^0=1 记录跳一步的最优位置
    }
    //递推
    for(int i=1;(1<<i)<=n;i++){//倍增
        forr(s,1,nt){
            go[s][i]=go[go[s][i-1]][i-1];//跳到2^(i-1)的跳板 再跳2^(i-1)
        }
    }
}
void fans(int x){
    int len=a[x].l+m;//绕一圈
    int ans=0,cur=x;
    reforr(i,0,(int)log2(N)){//从最大数开始跳
        int pos=go[cur][i];
        if(pos&&a[pos].l<len){
            ans+=(1<<i);
            cur=pos;//跳到新位置
        }
    }
    res[a[x].id]=ans+1;//排过序 不是以前的顺序了 输出答案要还原顺序
}
void solve()
{
	cin>>n>>m;
    forr(i,1,n){
        a[i].id=i;
        cin>>a[i].l>>a[i].r;
        if(a[i].r<a[i].l)a[i].r+=m;
    }
    sort(a+1,a+n+1,[](wa x,wa y){
        return x.l<y.l;
    });
    nt=n;
    forr(i,1,n){
        nt++,a[nt].l=a[i].l+m,a[nt].r=a[i].r+m;//拆环成链
    }
    init();
    forr(i,1,n) fans(i);
    forr(i,1,n)cout<<res[i]<<' ';

}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);

	int t=1;
    // cin>>t;
	while(t--) solve();
    
	return 0;
}

ST算法

用于求解静态数组RMQ(区间最值查询)问题

P2880 Balanced Lineup G

cpp 复制代码
const int N=5e4+10,M=20;
int n,m;
int a[N],l2[N];
int dpmn[N][M],dpmx[N][M];
void init(){
    l2[0]=-1;//log2递推计算
    forr(i,1,N)l2[i]=l2[i>>1]+1;
    forr(i,1,n){//初始化
        dpmx[i][0]=a[i];
        dpmn[i][0]=a[i];
    }
    int p=log2(n);
    //递推
    forr(i,1,p){//区间长度 小区间凑出大区间
        for(int s=1;s+(1<<i)<=n+1;s++){//左端点位置
            dpmx[s][i]=max(dpmx[s][i-1],dpmx[s+(1<<(i-1))][i-1]);
            dpmn[s][i]=min(dpmn[s][i-1],dpmn[s+(1<<(i-1))][i-1]);
        }
    }
}
int ans(int l,int r){
    int k=l2[r-l+1];//2^k<=len 2^(k+1)>=len 
    int mx=max(dpmx[l][k],dpmx[r-(1<<k)+1][k]);
    int mn=min(dpmn[l][k],dpmn[r-(1<<k)+1][k]);
    return mx-mn;
}
void solve()
{
	cin>>n>>m;
    forr(i,1,n){
        cin>>a[i];
    }
    init();
    forr(i,1,m){
        int l,r;
        cin>>l>>r;
        cout<<ans(l,r)<<endl;
    }
}
相关推荐
燃于AC之乐21 分钟前
我的算法修炼之路--4 ———我和算法的爱恨情仇
算法·前缀和·贪心算法·背包问题·洛谷
好奇龙猫6 小时前
【AI学习-comfyUI学习-第三十节-第三十一节-FLUX-SD放大工作流+FLUX图生图工作流-各个部分学习】
人工智能·学习
saoys6 小时前
Opencv 学习笔记:图像掩膜操作(精准提取指定区域像素)
笔记·opencv·学习
MM_MS6 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
独自破碎E6 小时前
【二分法】寻找峰值
算法
mit6.8247 小时前
位运算|拆分贪心
算法
电子小白1237 小时前
第13期PCB layout工程师初级培训-1-EDA软件的通用设置
笔记·嵌入式硬件·学习·pcb·layout
ghie90907 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab
恋爱绝缘体17 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit
wuk9987 小时前
VSC优化算法MATLAB实现
开发语言·算法·matlab