这题很妙,当时用CD的方法,写平衡树,但是吧没有领会精神,写了200多行,发现前驱后继又不合法的情况,好像要写12种情况,就不想写了。然后就突然明白线段树做法了。。。
介绍一种线段树做法:
本质思想是一样的,可能实现上优雅一点?
本质思想:动态开点,最多会有十万个点,完全可以,如果一段区间被覆盖一次之后,那么直接维护,如果没有被覆盖,我们需要在原序列上查询。
如果需要查询的区间在同一个周期内,直接查,如果大于一个周期,就是最小值,如果跨越两个区间,就很尴尬,可以将序列复制一遍,然后r = l + len - 1,查询。st表维护一下。会发现如果儿子没有被覆盖,那么一定是空。如果是空,那么直接查询,魔改pushup就行。
查询的话,如果说目前节点的区间为空,我们需要查询这个区间对应的原序列,左端点取max,右端点取min就行。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
const int INF = 1 << 30;
int n,k,q,b[N],rt,st[N << 1][21];
void St_pre(){
memset(st,0x3f,sizeof(st));
for(int i = 1;i <= n;++i)st[i][0] = b[i];
for(int i = n + 1;i <= 2 * n;++i)st[i][0] = b[i - n];
for(int i = 1;i <= 20;++i)for(int j = 1;j + (1 << i) - 1 <= n * 2;++j)st[j][i] = min(st[j][i - 1],st[j + (1 << (i - 1))][i - 1]);
}
int St_ask(int l,int r){
int ed = log2(r - l + 1);
return min(st[l][ed],st[r - (1 << ed) + 1][ed]);
}
int Ask(int l,int r){
int len = r - l + 1;
if(len >= n){
return St_ask(1,n);
}else{
l = (l % n == 0) ? n : (l % n);
return St_ask(l,l + len - 1);
}
}
struct Segment{
#define lson(p) t[p].ls
#define rson(p) t[p].rs
struct node{
int ls,rs,minn,lz;
node(){lz = 0;minn = INF;}
}t[N * 50];
int tot = 0;
Segment(){tot = 0;}
void pushup(int p,int l,int r){
int lw = INF,rw = INF,mid = l + r >> 1;
if(lson(p))lw = t[lson(p)].minn;
else lw = Ask(l,mid);
if(rson(p))rw = t[rson(p)].minn;
else rw = Ask(mid + 1,r);
t[p].minn = min(lw,rw);
}
void tag(int &p,int val){
if(!p)p = ++tot;
t[p].lz = val;
t[p].minn = val;
}
void pushdown(int p){
if(!t[p].lz)return;
tag(lson(p),t[p].lz);
tag(rson(p),t[p].lz);
t[p].lz = 0;
}
void modify(int &p,int L,int R,int l,int r,int val){
if(!p)p = ++tot;
if(l <= L && r >= R){
tag(p,val);
return;
}
pushdown(p);
int mid = L + R >> 1;
if(l <= mid)modify(lson(p),L,mid,l,r,val);
if(r > mid)modify(rson(p),mid + 1,R,l,r,val);
pushup(p,L,R);
}
int query(int p,int L,int R,int l,int r){
if(l > r)return INF;
if(!p)return Ask(max(l,L),min(r,R));
if(l <= L && r >= R)return t[p].minn;
int mid = L + R >> 1;
pushdown(p);
int res = 1 << 30;
if(l <= mid)res = min(res,query(lson(p),L,mid,l,r));
if(r > mid)res = min(res,query(rson(p),mid + 1,R,l,r));
return res;
}
}S;
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>k;
for(int i = 1;i <= n;++i)cin>>b[i];
St_pre();
cin>>q;
for(int i = 1;i <= q;++i){
int opt,l,r,x;
cin>>opt>>l>>r;
if(opt & 1){
cin>>x;
S.modify(rt,1,n * k,l,r,x);
}else cout<<S.query(rt,1,n * k,l,r)<<"\n";
}
return 0;
}