1 条题解

  • 0
    @ 2021-6-15 13:59:40

    C++ :

    /*
    线段树套权值线段树
    外层权值线段树维护每个数字出现的次数,内层维护在每个区间出现次数,然后外层二分查找,内层query区间和
    边运行边建树,防止MLE
    */
    #include<cstdio>
    using namespace std;
    int n,m,n1,n2,n3,n4,k,num,room,tot1,tot2;
    inline void read(int&a){
      char ch;while(!((ch=getchar())>='0')&&(ch<='9'));
      a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';
    }
    struct node1{int l,r,t;}tree1[10000000];
    struct node2{int l,r,tmp;long long f;}tree2[10000000];
    void cover(int p,int l,int r){
      int mid=(l+r)>>1;
      if((l>=n2)&&(r<=n3)){
        ++tree2[p].tmp;
        return;
      }
      if(tree2[p].tmp){
        if(!tree2[p].l)tree2[p].l=++tot2;
        if(!tree2[p].r)tree2[p].r=++tot2;
      }
      if(n3<=mid){
        if(!tree2[p].l)tree2[p].l=++tot2;
        if(tree2[p].tmp){
          tree2[tree2[p].l].tmp+=tree2[p].tmp;
          tree2[tree2[p].r].tmp+=tree2[p].tmp;
          tree2[p].tmp=0;
        }
        cover(tree2[p].l,l,mid);
      }else{
        if(n2>mid){
          if(!tree2[p].r)tree2[p].r=++tot2;
          if(tree2[p].tmp){
            tree2[tree2[p].r].tmp+=tree2[p].tmp;
            tree2[tree2[p].l].tmp+=tree2[p].tmp;
            tree2[p].tmp=0;
          }
          cover(tree2[p].r,mid+1,r);
        }else{
          if(!tree2[p].l)tree2[p].l=++tot2;
          if(!tree2[p].r)tree2[p].r=++tot2;
          if(tree2[p].tmp){
            tree2[tree2[p].l].tmp+=tree2[p].tmp;
            tree2[tree2[p].r].tmp+=tree2[p].tmp;
            tree2[p].tmp=0;
          }
          cover(tree2[p].l,l,mid);
          cover(tree2[p].r,mid+1,r);
        }
      }
      tree2[p].f=0;
      if(tree2[p].l)tree2[p].f+=tree2[tree2[p].l].tmp*(r-mid)+tree2[tree2[p].l].f;
      if(tree2[p].r)tree2[p].f+=tree2[tree2[p].r].tmp*(r-mid)+tree2[tree2[p].r].f;
    }
    void build(int p,int l,int r){
      if(!tree1[p].t)tree1[p].t=++tot2;
      cover(tree1[p].t,1,room);
      if(l==r)return;
      int mid=(l+r)>>1;
      if(n4<=mid){
        if(!tree1[p].l)tree1[p].l=++tot1;
        build(tree1[p].l,l,mid);
      }else{
        if(!tree1[p].r)tree1[p].r=++tot1;
        build(tree1[p].r,mid+1,r);
      }
    }
    long long find(int p,int l,int r){
      int t1,t2;
      if((!tree2[p].l)&&(!tree2[p].r)){
        t1=n2>l?n2:l;t2=n3<r?n3:r;
        return tree2[p].tmp*(t2-t1+1);
      }
      if((l>=n2)&&(r<=n3))return tree2[p].tmp*(r-l+1)+tree2[p].f;
      long long tmp=0;
      int mid=(l+r)>>1;
      if(n3<=mid){
        if(tree2[p].l)tmp+=find(tree2[p].l,l,mid);
      }else{
        if(n2>mid){
          if(tree2[p].r)tmp+=find(tree2[p].r,mid+1,r);
        }else{
          if(tree2[p].l)tmp+=find(tree2[p].l,l,mid);
          if(tree2[p].r)tmp+=find(tree2[p].r,mid+1,r);
        }
      }
      t1=n2>l?n2:l;t2=n3<r?n3:r;
      return tmp+tree2[p].tmp*(t2-t1+1);
    }
    int ask(int p,int l,int r){
      if(l==r)return l;
      int mid=(l+r)>>1,tmp;
      if(tree1[p].r){
        tmp=find(tree1[tree1[p].r].t,1,room);
        if(tmp>=n4)return ask(tree1[p].r,mid+1,r);else n4-=tmp;
      }
      return ask(tree1[p].l,l,mid);
    }
    int main(){
      read(n);read(m);
      num=room=tot1=1;
      while(num<=n+1)num<<=1;
      while(room<=n)room<<=1;
      while(m--){
        read(n1);read(n2);read(n3);read(n4);
        if(n1==1)build(1,0,num-1);else printf("%d\n",ask(1,0,num-1));
      }
      return 0;
    }
    
    • 1

    信息

    ID
    967
    时间
    2000ms
    内存
    512MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者