weinan030416

导航

第几小

 

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
  // 请在此输入您的代码
  int n;
    cin>>n;
  //块长
  int len=sqrt(n)*log(n)/2;
  //块数
  int k=(n%len==0)?n/len:n/len+1;
  //分块
  vector<int> block[k+1];
  //第i个数属于的块
  vector<int> belong(n+1,0);
    vector<int> a(n+1,0);
  int blockNum=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    blockNum=(i-1)/len+1;
    belong[i]=blockNum;
    block[blockNum].push_back(a[i]);
    }
  //对分块进行排序
  for(int i=1;i<=k;i++){
    sort(block[i].begin(),block[i].end(),less<int>());
  }
  //记录操作
    int m;
    cin>>m;
    vector<vector<int>> op(m,vector<int>(4,0));
    for(int i=0;i<m;i++){
         cin>>op[i][0];
         if(op[i][0]==1){
            //修改操作
            for(int j=1;j<=2;j++){
                cin>>op[i][j];
            }             
         }else{
             //查询操作
             for(int j=1;j<=3;j++){
                 cin>>op[i][j];
             } 
         }
    }
  //执行操作
    vector<int> res;
    int num1,num2,num3;
    num1=num2=num3;
    int count=0;
  int mid=0;
    for(int i=0;i<m;i++){
        num1=op[i][1];
        num2=op[i][2];
        num3=op[i][3];
        if(op[i][0]==1){
      //修改分组
      auto it=lower_bound(block[belong[num1]].begin(),block[belong[num1]].end(),a[num1]);
      block[belong[num1]].erase(it);
      it=lower_bound(block[belong[num1]].begin(),block[belong[num1]].end(),num2);
      if(it==block[belong[num1]].end()){
        block[belong[num1]].push_back(num2);
      }else{
        block[belong[num1]].insert(it,num2);
      }
      //修改原序列
            a[num1]=num2;
        }else{
      count=0;
      mid=a[num3];
      //先查左右两端分块中满足条件的元组数,因为num1和num2所在的块不一定一整块都参与比较
      for(int j=num1;j<=min(num2,belong[num1]*len);j++){
        if(a[j]<mid){
          count++;
        }
      }
      if(belong[num1]!=belong[num2]){
        for(int j=(belong[num2]-1)*len+1;j<=num2;j++){
          if(a[j]<mid){
            count++;
          }
        }
      }
      //区间查询,用二分法查询每个块中小于a[p]的元素个数
      for(int j=belong[num1]+1;j<=belong[num2]-1;j++){
        count+=lower_bound(block[j].begin(),block[j].end(),a[num3])-block[j].begin();
      }
      res.push_back(count+1);
      //49 31 31 11 24 8 4 62 7 11 46 47 3 20 16 24 29 11 2 4 5 16 3 68 
        }
    }
    for(auto &&num:res){
        cout<<num<<" ";
    }
  return 0;
}

 

posted on 2023-02-13 21:07  楠030416  阅读(21)  评论(0编辑  收藏  举报