Description
维护一个数据结构,资瓷区间取min和区间求k小值。
n<=8*1e4
Solution
和由乃OI那题很像,直接分块,块内归并重构,二分答案块内二分查询。
只不过比较良心的是JZOJ上不卡常,但是我块大小开n√lognT了,开n√过了。。。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,a) for(int i=lst[a];i;i=nxt[i])
using namespace std;
int read() {
char ch;
for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
int x=ch-'0';
for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x;
}
void write(int x) {
if (!x) {puts("0");return;}
if (x<0) {putchar('-');x=-x;}
char ch[20];int tot=0;
for(;x;x/=10) ch[++tot]=x%10+'0';
fd(i,tot,1) putchar(ch[i]);
puts("");
}
inline int min(int x,int y) {return x<y?x:y;}
const int N=8*1e4+5,M=500;
struct P{int v,w;}a[N],b[N],c[N];
bool cmp(P x,P y) {return x.v<y.v;}
int bl[N],L[N],R[N],lazy[N],Sz,n,m;
int find(int w) {fo(i,1,Sz) if (L[i]<=w&&w<=R[i]) return i;}
int p[N],q[N];
bool bz[N];
void rebuild(int v,int l,int r,int k) {
fo(i,L[v],R[v]) bz[i]=0;
fo(i,l,r) a[i].v=min(a[i].v,k),bz[a[i].w]=1;
q[0]=p[0]=0;
fo(i,L[v],R[v])
if (bz[i]) q[++q[0]]=i;
else p[++p[0]]=i;
int i=1,j=1,cnt=0;
while (i<=q[0]&&j<=p[0]) {
if (min(b[q[i]].v,k)<b[p[j]].v) {c[++cnt]=b[q[i++]];c[cnt].v=min(c[cnt].v,k);}
else c[++cnt]=b[p[j++]];
}
while (i<=q[0]) {c[++cnt]=b[q[i++]];c[cnt].v=min(c[cnt].v,k);}
while (j<=p[0]) c[++cnt]=b[p[j++]];
fo(i,1,cnt) b[L[v]+i-1]=c[i];
fo(i,L[v],R[v]) a[b[i].w].w=i;
}
int len,opt,x,k,z,l,r,u,v;
int solve(int u,int l,int r,int v) {
int cnt=0;
fo(i,l,r) if (min(a[i].v,lazy[u])<=v) cnt++;
return cnt;
}
int query(int u,int v) {
int l=L[u],r=R[u]+1;
while (l<r) {
int mid=l+r>>1;
if (min(b[mid].v,lazy[u])<=v) l=mid+1;
else r=mid;
}
return l-L[u];
}
int check(int mid) {
int res=0;
if (u==v) return solve(u,l,r,mid);
res=solve(u,l,R[u],mid)+solve(v,L[v],r,mid);
fo(i,u+1,v-1) res+=query(i,mid);
return res;
}
int main() {
n=read();m=read();
fo(i,1,n) a[i].v=read(),a[i].w=i;
fo(i,1,n) bl[i]=(i-1)/M+1;Sz=bl[n];
fo(i,1,Sz) L[i]=R[i-1]+1,R[i]=min(L[i]+M-1,n);
fo(i,1,Sz) {
lazy[i]=n+1;
fo(j,L[i],R[i]) b[j]=a[j];
sort(b+L[i],b+R[i]+1,cmp);
fo(j,L[i],R[i]) a[b[j].w].w=j;
}
for(;m;m--) {
opt=read();l=read();r=read();k=read();
if (!k) {write(1);continue;}
u=find(l);v=find(r);
if (opt==2) {
int le=0,ri=n+1;
while (le<ri) {
int mid=le+ri>>1;
if (check(mid)>=k) ri=mid;
else le=mid+1;
}
write(le);
} else {
if (u==v) {rebuild(u,l,r,k);continue;}
fo(i,u+1,v-1) lazy[i]=min(lazy[i],k);
rebuild(u,l,R[u],k);rebuild(v,L[v],r,k);
}
}
return 0;
}