zoukankan      html  css  js  c++  java
  • 超级钢琴 && ST表复习笔记

    ST表

    好久没写了, 所以写篇博客来回忆一下

    用于解决RMQ问题

    主要运用倍增的思想

    具体做法:

    1. 设f[i][j]为 $ [i,i+2^j] $ 区间内的极值, 然后预处理

    2. 查询时: 设查询区间长度为len,返回左端点为起点长度为$ 2^{log_2(len)} $ 与右端点为终点同等长度的二者中的极值

    (此处log需要下取整)

    void prepare()
    {
        lg[0]=-1;
        for(re int i=1;i<=n;++i) lg[i]=lg[i/2]+1;
        for(re int i=1;i<=lg[n];++i)
            for(re int j=1;j<=n;++j)
                f[j][i]=MAX(f[j][i-1], f[j+(1<<i-1)][i-1]);
    }
    int query(int l,int r)
    {
        int LOG=lg[r-l+1];
        return MAX(f[l][LOG],f[r-(1<<LOG)+1][LOG]);
    }
    
    

    NOI2010 超级钢琴

    题意简述:
    对于一个长为n的序列求k段不同的长度在[L,R]中的区间, 使得选中的序列和的总和最大
    n,m<=500000

    Sol

    常用小技巧: 碰到区间权值问题,可以考虑前缀和,转化为点权,然后运用数据结构即可

    此题也是如此, 先转化为对于每个点,考虑其作为起点,则需要在之后[L,R]的区间中找到最大值
    将所有最大值放入堆中,每弹出一次,就将该区间拆开

    code

    #include<bits/stdc++.h>
    using namespace std;
    #define re register
    #define in inline
    #define get getchar()
    #define ll long long
    in int read()
    {
        int t=0, x=1; char ch=get;
        while(ch!='-' && (ch<'0' || ch>'9') ) ch=get;
        if(ch=='-') ch=get, x=-1;
        while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
        return t*x;
    }
    const int _=1e6+23;
    const int LG=22;
    int f[_][LG],n,k,L,R,a[_],lg[_];
    in int MAX(int x,int y){ return a[x]>a[y] ? x : y;}
    in int query(int l,int r)
    {
        int LOG=lg[r-l+1];
        return MAX(f[l][LOG],f[r-(1<<LOG)+1][LOG]);
    }
    struct yzx{
        int l,r,num;
        int val(){ return a[query(l,r)] - a[num-1];}
    }; //表示每个可能最大值区间右端点范围[l,r],以及左端点编号num
    yzx YZX(int a,int b,int c){return yzx{a,b,c}; }
    bool operator < (yzx x,yzx y){ return x.val() < y.val(); }
    priority_queue<yzx> q;
    int main()
    {
        n=read(), k=read(), L=read(), R=read();
        lg[0]=-1;
        for(re int i=1;i<=n;++i) a[i]=read()+a[i-1], f[i][0]=i, lg[i]=lg[i/2]+1;
        for(re int i=1;i<=lg[n];++i)
            for(re int j=1;j<=n;++j)
                f[j][i]=MAX(f[j][i-1], f[j+(1<<i-1)][i-1]);
        for(re int i=1;i<=n;++i) {
            int st=i+L-1;
            if(st>n) break;
            q.push(YZX(st,min(n,st+(R-L)),i));
        }
        ll ans=0;
        while(k--)
        {
            yzx u=q.top(); q.pop();
            ans+=u.val();
            int pos=query(u.l,u.r);
            if(pos>u.l) q.push(YZX(u.l,pos-1,u.num));
            if(pos<u.r) q.push(YZX(pos+1,u.r,u.num));
        }
        cout<<ans<<endl;
        return 0;
    }
    
    嗯,就这样了...
  • 相关阅读:
    程序员外包网站
    网络测试
    数据库系统在线网课
    字体
    正则表达式测试工具
    豆瓣Top250数据可视化
    前端模板
    豆瓣Top250电影爬取
    PyCharm激活码
    爬虫禁止访问解决方法(403)
  • 原文地址:https://www.cnblogs.com/yzhx/p/14783003.html
Copyright © 2011-2022 走看看