[LibreOJ β Round]ZQC的手办

来源:互联网 发布:淘宝上买手办的 编辑:程序博客网 时间:2024/04/27 22:44

题目大意

区间对一个数取max。
区间求最小的x个比k小的数。

线段树

第一个操作很好搞。
第二个操作有个很显然的常数大做法。
实际上可以用堆把这个区间的笛卡尔树按优先级广搜。

#include<cstdio>#include<algorithm>#include<queue>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=500000+10,inf=1000000000;struct dong{    int x,y;    friend bool operator <(dong a,dong b){        return a.x<b.x||a.x==b.x&&a.y<b.y;    }    friend dong operator +(dong a,dong b){        if (a<b) return a;else return b;    }} tmp;struct suan{    int l,r,p,v;    friend bool operator <(suan a,suan b){        return a.v>b.v||a.v==b.v&&a.p<b.p;    }} zlt;priority_queue<suan> dl;dong tree[maxn*4];int mx[maxn*4],a[maxn],ans[maxn],sta[80];bool bz[maxn*4];int i,j,k,l,r,p,t,n,m,tot,top;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}void build(int p,int l,int r){    if (l==r){        tree[p].x=a[l];        tree[p].y=l;        return;    }    int mid=(l+r)/2;    build(p*2,l,mid);    build(p*2+1,mid+1,r);    tree[p]=tree[p*2]+tree[p*2+1];}void mark(int p,int v){    bz[p]=1;    mx[p]=max(mx[p],v);    if (tree[p].x<v) tree[p].x=v;}void down(int p){    if (bz[p]){        mark(p*2,mx[p]);        mark(p*2+1,mx[p]);        bz[p]=0;    }}void change(int p,int l,int r,int a,int b,int v){    if (l==a&&r==b){        mark(p,v);        return;    }    down(p);    int mid=(l+r)/2;    if (b<=mid) change(p*2,l,mid,a,b,v);    else if (a>mid) change(p*2+1,mid+1,r,a,b,v);    else change(p*2,l,mid,a,mid,v),change(p*2+1,mid+1,r,mid+1,b,v);    tree[p]=tree[p*2]+tree[p*2+1];}void query(int p,int l,int r,int a,int b){    if (l==a&&r==b){        tmp=tmp+tree[p];        return;    }    down(p);    int mid=(l+r)/2;    if (b<=mid) query(p*2,l,mid,a,b);    else if (a>mid) query(p*2+1,mid+1,r,a,b);    else query(p*2,l,mid,a,mid),query(p*2+1,mid+1,r,mid+1,b);}int main(){    n=read();    fo(i,1,n) a[i]=read();    build(1,1,n);    m=read();    fo(i,1,m){        t=read();        if (t==1){            l=read();r=read();k=read();            change(1,1,n,l,r,k);        }        else{            l=read();r=read();k=read();j=read();            if (r-l+1<j){                printf("-1\n");                continue;            }            while (!dl.empty()) dl.pop();            zlt.l=l;zlt.r=r;            tmp.x=inf;            query(1,1,n,l,r);            zlt.p=tmp.y;zlt.v=tmp.x;            dl.push(zlt);            tot=0;            while (j--){                zlt=dl.top();                dl.pop();                if (zlt.v>=k) break;                ans[++tot]=zlt.v;                l=zlt.l;r=zlt.r;p=zlt.p;                if (l<p){                    zlt.l=l;                    zlt.r=p-1;                    tmp.x=inf;                    query(1,1,n,l,p-1);                    zlt.p=tmp.y;zlt.v=tmp.x;                    dl.push(zlt);                }                if (p<r){                    zlt.l=p+1;                    zlt.r=r;                    tmp.x=inf;                    query(1,1,n,p+1,r);                    zlt.p=tmp.y;zlt.v=tmp.x;                    dl.push(zlt);                }            }            if (j>=0) printf("-1\n");            else{                fo(j,1,tot) printf("%d ",ans[j]);                printf("\n");            }        }    }}
原创粉丝点击