【清华集训2017模拟11.29】K小数查询

来源:互联网 发布:程序员图像 编辑:程序博客网 时间:2024/05/22 08:03

Description

维护一个数据结构,资瓷区间取min和区间求k小值。
n<=8*1e4

Solution

和由乃OI那题很像,直接分块,块内归并重构,二分答案块内二分查询。
只不过比较良心的是JZOJ上不卡常,但是我块大小开nlognT了,开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;}