题目链接: G Periodic RMQ Problem
题意:一个长度为n的序列,重复k次,构成1e9的序列,然后区间修改,区间查询最小值
思路:ST表预处理区间最值,线段树动态开点
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int ls[N<<7],rs[N<<7]; int mn[N<<7],lazy[N<<7]; int Log[N],a[N],f[N][20]; int cnt=1,q,n,ans,k; void init(){ Log[0]=-1; for(int i=1;i<=n;i++) f[i][0]=a[i],Log[i]=Log[i>>1]+1; for(int j=1;j<=19;j++) for(int i=1;i+(1<<(j-1))<=n;i++) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } int RMQ(int x,int y){ int t=Log[y-x+1]; return min(f[x][t],f[y-(1<<t)+1][t]); } int qry(int l,int r){ if(r-l>=n)return RMQ(1,n); else{ l=(l-1)%n+1,r=(r-1)%n+1; if(l>r)return min(RMQ(1,r),RMQ(l,n)); else return RMQ(l,r); } } void pushdown(int p,int l,int r){ int mid=(l+r)>>1; if(!ls[p]) ls[p]=++cnt;if(!rs[p]) rs[p]=++cnt; if(~lazy[p]){ lazy[ls[p]]=lazy[rs[p]]=lazy[p]; mn[ls[p]]=lazy[ls[p]]?lazy[ls[p]]:qry(l,mid); mn[rs[p]]=lazy[rs[p]]?lazy[rs[p]]:qry(mid+1,r); } } void update(int x,int y,int l,int r,int p,int t){ if(l>=x&&r<=y){mn[p]=lazy[p]=t;return;} int mid=(l+r)>>1;pushdown(p,l,r);lazy[p]=-1; if(mid>=x) update(x,y,l,mid,ls[p],t); if(mid<y) update(x,y,mid+1,r,rs[p],t); mn[p]=min(mn[ls[p]],mn[rs[p]]); } void query(int x,int y,int l,int r,int p){ if(l>=x&&r<=y){ans=min(ans,mn[p]);return;} int mid=(l+r)>>1;pushdown(p,l,r);lazy[p]=-1; if(mid>=x) query(x,y,l,mid,ls[p]); if(mid<y) query(x,y,mid+1,r,rs[p]); mn[p]=min(mn[ls[p]],mn[rs[p]]); } int main(){ scanf("%d%d",&n,&k);int mn_=1e9; for(int i=1;i<=n;i++) scanf("%d",&a[i]),mn_=min(mn_,a[i]); scanf("%d",&q);init(); int t,l,r,x;mn[1]=mn_; while(q--){ scanf("%d%d%d",&t,&l,&r); if(t==1){scanf("%d",&x);update(l,r,1,n*k,1,x);} else{ ans=1e9;query(l,r,1,n*k,1); printf("%d\n",ans); } } return 0; }