首页 > 其他分享 >CF803G Periodic RMQ Problem

CF803G Periodic RMQ Problem

时间:2023-11-10 22:46:46浏览次数:34  
标签:RMQ return rs int mn tree Periodic CF803G define

题目描述

给你一个序列\(a\) 让你支持

\(1\) \(l\) \(r\) \(x\) 区间赋值

\(2\) \(l\) \(r\) 询问区间最小值

我们觉得这个问题太水了,所以我们不会给你序列\(a\)

而是给你序列一个长度为\(n\) 的序列\(b\) ,把\(b\) 复制粘贴\(k\) 次就可以得到\(a\)

\(n\le10^5,k\le10^4,q\le10^5,b_i\le10^9\)

\(1\le l\le r\le n\times k\)

感谢@Kelin 提供的翻译

思路:

对于这种类型的题目,我们先考虑一个简化版的问题:如果没有修改操作,怎么做?

解法:

显然我们可以进行分类讨论:

  1. \(r-l+1\ge n\) 则答案为 \(Min(0,n-1)\)
  2. \(r-l+1<n \ \land \ \frac{l}{n}=\frac{r}{n}\) 则答案为 \(Min(l\%n,r\%n)\)
  3. \(r-l+1<n \ \land \ \frac{l}{n}\neq \frac{r}{n}\) 则答案为 \(\min(Min(l\%n,n-1),Min(0,r\%n))\)

然后我们回归这个题目,显然我们如果将整棵线段树建出来,时间复杂度 \(O(nk\log_2 (nk))\),空间复杂度 \(O(nk)\),全部爆掉了。
所以我们要尝试优化这个东西。

首先思考怎么优化空间:

可以考虑使用动态开点线段树,空间复杂度应该是 \(O(q\log_2(nk))\) 大概是这样吧……

然后考虑怎么优化时间:

发现其实复杂度堆积的地方是在建树的部分,复杂度达到了 \(O(nk)\)

所以我们不妨尝试能否不在一开始就建出完整的树。顺着一开始动态开点的顺序思考这个问题。

如果我们根据询问来动态开点,则对于一次修改操作,我们可以将他修改的部分进行标记,其他位置不需要标记。
对于一次询问操作,对于修改的部分我们就遍历一下,否则就在原序列上比较。

然后就可以通过一开始的引例的解法来解决问题了。

具体的代码实现其实也比较简单,没什么思维难度。主要是如果见过类似的题目就会比较简单。

点击查看代码
#include<bits/stdc++.h>
#define mem(a) memset(a,0,sizeof(a))
#define set(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pt putchar
#define All(a) a.begin(),a.end()
#define T int t;cin>>t;while(t--)
#define rand RAND
using namespace std;
char buf[1<<20],*p1,*p2;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
template<class Typ> Typ &re(Typ &x){char ch=gc(),sgn=0; x=0;for(;ch<'0'||ch>'9';ch=gc()) sgn|=ch=='-';for(;ch>='0'&&ch<='9';ch=gc()) x=x*10+(ch^48);return sgn&&(x=-x),x;}
template<class Typ> void wt(Typ x){if(x<0) putchar('-'),x=-x;if(x>9) wt(x/10);putchar(x%10^48);}
const int maxn=1e5+5;
const int N=2e7+5;
const int mod=1e9+7;
int seed = 19243;
unsigned rand(){return seed=(seed*48271ll)%2147483647;}
int n,k;
int a[maxn];
namespace RMQ{
    int st[maxn][20];
    void init(){
        for(int j=1;j<=18;j++){
            for(int i=0;i+(1<<j)-1<n;i++){
                st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int Mn(int l,int r){
        int k=log2(r-l+1);
        return min(st[l][k],st[r-(1<<k)+1][k]);
    }
}using namespace RMQ;
int rt;
namespace Seg{
    struct node{
        int mn,tg;
    }tree[N];
    int ls[N],rs[N];
    int idx=0;
    int newnode(int l,int r){
        idx++;
        if(r-l+1>=n)tree[idx].mn=Mn(0,n-1);
        else if(l/n==r/n)tree[idx].mn=Mn(l%n,r%n);
        else tree[idx].mn=min(Mn(l%n,n-1),Mn(0,r%n));
        return idx;
    }
    void push_down(int x,int l,int r){
        int mid=(l+r)>>1;
        if(!ls[x])ls[x]=newnode(l,mid);
        if(!rs[x])rs[x]=newnode(mid+1,r);
        if(!tree[x].tg)return ;
        tree[ls[x]].mn=tree[ls[x]].tg=tree[rs[x]].mn=tree[rs[x]].tg=tree[x].tg;
        tree[x].tg=0;
        return ;
    }
    void push_up(int x){
        tree[x].mn=min(tree[ls[x]].mn,tree[rs[x]].mn);
        return ;
    }
    void update(int &x,int l,int r,int L,int R,int val){
        if(!x)x=newnode(l,r);
        if(L<=l&&R>=r){
            tree[x].mn=tree[x].tg=val;
            return ;
        }
        int mid=(l+r)>>1;
        push_down(x,l,r);
        if(L<=mid)update(ls[x],l,mid,L,R,val);
        if(R>mid)update(rs[x],mid+1,r,L,R,val);
        push_up(x);
    }
    int query(int &x,int l,int r,int L,int R){
        if(!x)x=newnode(l,r);
        if(L<=l&&R>=r){
            return tree[x].mn;
        }
        int mid=(l+r)>>1;
        push_down(x,l,r);
        int res=1e18;
        if(L<=mid)res=min(res,query(ls[x],l,mid,L,R));
        if(R>mid)res=min(res,query(rs[x],mid+1,r,L,R));
        return res;
    }
}using namespace Seg;
signed main(){
    cin>>n>>k;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int i=0;i<n;i++)st[i][0]=a[i];
    init();
    int Q;cin>>Q;
    while(Q--){
        int op;
        cin>>op;
        if(op==1){
            int l,r,c;cin>>l>>r>>c;
            l--,r--;
            update(rt,0,n*k-1,l,r,c);
        }
        else{
            int l,r;
            cin>>l>>r;
            l--,r--;
            cout<<query(rt,0,n*k-1,l,r)<<endl;
        }
    }
    return 0;
}

标签:RMQ,return,rs,int,mn,tree,Periodic,CF803G,define
From: https://www.cnblogs.com/Candycar/p/17825143.html

相关文章

  • RMQ模板
    #include<cstdio>#include<cstring>#include<algorithm>#include<cmath>usingnamespacestd;constintN=200010,M=18;intn,m;intw[N];intlg[N];intf[N][M];//查询区间最值//预处理f数组voidinit(){ lg[1]=0; for(inti=2;i&l......
  • P6109 [Ynoi2009] rprmq1 题解-猫树+Segment Tree Beats
    20231025P6109[Ynoi2009]rprmq1题解-猫树+SegmentTreeBeats不愧是学长出的题。。。让我更深刻地理解了猫树。Statement传送门有一个\(n\timesn\)的矩阵\(a\),初始全是\(0\),有\(m\)次修改操作和\(q\)次查询操作,先进行所有修改操作,然后进行所有查询操作。一次修......
  • RMQ
    P3865【模板】ST表利用倍增f[i][j]表示,范围[i,i+2^(j)-1]内的最大值是多少点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=1e5+10;intf[N][22];intmain(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); intn,m; cin>>n>>......
  • 分块+ST的RMQ
    期望\(O(n)-O(1)的RMQ\)#include<bits/stdc++.h>#defineintlonglong#defineF(i0,i1,i2)for(inti0=(i1);i0<=(i2);++i0)usingnamespacestd;inlineintrd(){ intx=0,f=0;charch=getchar(); while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar(......
  • RockerMq发送消息之顺序消息
    顺序消息        消息有序指的是可以按照消息的发送顺序来消费(FIFO)。RocketMQ可以严格的保证消息有序,可以分为分区有序或者全局有序。        顺序消费的原理解析,在默认的情况下消息发送会采取RoundRobin轮询方式把消息发送到不同的queue(分区队列);而消费消......
  • 基于Docker安装RockerMQ
    1、拉取RockerMQ镜像dockerpullapache/rocketmq2、创建namesrv服务mkdir-p/usr/local/rocketmq/data/namesrv/logs/usr/local/rocketmq/data/namesrv/store3、构建namesrv容器 dockerrun-d\--restart=always\--namermqnamesrv\--privileged=true\-p98......
  • 【树论】RMQ问题和ST表
    目录RMQ问题ST表优缺点实现递推查询复杂度代码技巧-快速读入RMQ问题RMQ(RangeMaximum/MinimumQuery)问题,即区间最值问题。一般是多次询问,对时间复杂度要求高,一般需要\(O(logn)\)或\(O(1)\)复杂度ST表p[i][j]是以i为起点,连续\(2^j\)个数字的最大值(是一个递推表)3......
  • RMQ问题中的ST算法
    RMQ问题中的ST算法长为n的数组a,m次询问,求l~r中最大值是多少//RMQ问题中的ST算法//m次询问,求l~r中最大值是多少#include<bits/stdc++.h>#defineregregisterusingnamespacestd;//读取输入的函数inlineintread(){ intx=0,f=1; charch=getchar(); while(ch......
  • RMQ模板
    template<calssT>structRMQ{intn;vector<vector<T>>f;vector<int>log_2;vector<T>a;function<T(T,T)>cmp;RMQ(){}RMQ(intn,function<T(T,T)>op):n(n),f(n+5,ve......
  • uva 12299 RMQ with Shifts(线段树单点更新初步应用)
                                 uva12299RMQwithShiftsInthetraditionalRMQ(RangeMinimumQuery)problem,wehaveastaticarrayA.Thenforeachquery(L,R)(LR),wereporttheminimumvalueamongA[L],A[L+1],...,A[R].N......