• [Tyvj 1730] 二逼平衡树


    先来一发题面QwQ

    [TYVJ1730]二逼平衡树

    Time Limit:2 s   Memory Limit:512 MB

    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
    1.查询k在区间内的排名
    2.查询区间内排名为k的值
    3.修改某一位值上的数值
    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    Input

    第一行两个数 n,m 表示长度为n的有序序列和m个操作
    第二行有n个数,表示有序序列
    下面有m行,opt表示操作标号
    若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    Output

    对于操作1,2,4,5各输出一行,表示查询结果

    Sample Input

    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5

    Sample Output

    2
    4
    3
    4
    9

    Hint

    n,m<=50000   保证有序序列所有值在任何时刻满足[0,10^8]但是询问的数未必

    这题正解似乎是树套树(线段树套平衡树)

    然而我用分块大法水过去了233

    分块的话思路还是比较明确的,比如对于求排名操作(操作1),对于两端的块我们可以选择直接暴力查询比$key$值小的值的个数,中间的完整块可以选择二分查找($std::lower\_bound$)来得出比$key$小的元素个数,累加起来加上1就是答案了.

    求K大的话比较麻烦,要二分第K大的值然后用求排名操作来检验...

    修改直接暴力修改不解释

    前驱/后继则可以用上面求排名的方式来查找,不同的是对于比$key$小/大的元素不应累加而是求最大/小值.

    然后就到了袋马时间~(突然感觉好草率啊QwQ)

    GitHub:BlockSearch

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cctype>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <iostream>
      7 #include <algorithm>
      8 
      9 const int MAXN=50010;
     10 const int MAXB=230;
     11 const int INF=0x7FFFFFFF;
     12 
     13 int n,m;
     14 int endSize;
     15 int blockNum;
     16 int blockSize;
     17 int data[MAXN];
     18 int block[MAXN][MAXB];
     19 
     20 void Initialize();
     21 void FastRead(int&);
     22 void Modify(int,int);
     23 int Kth(int,int,int);
     24 int Rank(int,int,int);
     25 int Predecessor(int,int,int);
     26 int Successor(int,int,int);
     27 
     28 int main(){
     29     int opt,l,r,num;
     30     Initialize();
     31     for(int i=0;i<m;i++){
     32         scanf("%d",&opt);
     33         if(opt==1){
     34             FastRead(l);
     35             FastRead(r);
     36             FastRead(num);
     37             printf("%d
    ",Rank(l-1,r-1,num));
     38         }
     39         else if(opt==2){
     40             FastRead(l);
     41             FastRead(r);
     42             FastRead(num);
     43             printf("%d
    ",Kth(l-1,r-1,num));
     44         }
     45         else if(opt==3){
     46             FastRead(l);
     47             FastRead(num);
     48             Modify(l-1,num);
     49         }
     50         else if(opt==4){
     51             FastRead(l);
     52             FastRead(r);
     53             FastRead(num);
     54             printf("%d
    ",Predecessor(l-1,r-1,num));
     55         }
     56         else{
     57             FastRead(l);
     58             FastRead(r);
     59             FastRead(num);
     60             printf("%d
    ",Successor(l-1,r-1,num));
     61         }
     62     }
     63     return 0;
     64 }
     65 
     66 inline int Rank(int l,int r,int key){
     67     int lb=l/blockSize;
     68     int rb=r/blockSize;
     69     int ans=1;
     70     if(lb==rb){
     71         for(int i=l;i<=r;i++){
     72             if(data[i]<key){
     73                 ans++;
     74             }
     75         }
     76     }
     77     else{
     78         for(int i=l;i<(lb+1)*blockSize;i++){
     79             if(data[i]<key){
     80                 ans++;
     81             }
     82         }
     83         for(int i=rb*blockSize;i<=r;i++){
     84             if(data[i]<key){
     85                 ans++;
     86             }
     87         }
     88         for(int i=lb+1;i<rb;i++){
     89             ans+=std::lower_bound(block[i],block[i]+blockSize,key)-block[i];
     90         }
     91     }
     92     return ans;
     93 }
     94 
     95 inline int Kth(int l,int r,int pos){
     96     int L=-1;
     97     int R=100000010;
     98     while(R-L>1){
     99         int mid=(L+R)>>1;
    100         if(Rank(l,r,mid)>pos)
    101             R=mid;
    102         else
    103             L=mid;
    104     }
    105     return R-1;
    106 }
    107 
    108 inline void Modify(int pos,int key){
    109     if(data[pos]==key)
    110         return;
    111     int* thisBlock=block[pos/blockSize];
    112     int old=data[pos];
    113     int size=(pos/blockSize)==blockNum?endSize:blockSize;
    114     data[pos]=key;
    115     pos=std::lower_bound(thisBlock,thisBlock+size,old)-thisBlock;
    116     thisBlock[pos]=key;
    117     std::sort(thisBlock,thisBlock+size);
    118 }
    119 
    120 inline int Predecessor(int l,int r,int key){
    121     int lb=l/blockSize;
    122     int rb=r/blockSize;
    123     int ans=-INF;
    124     if(lb==rb){
    125         for(int i=l;i<=r;i++){
    126             if(data[i]<key)
    127                 ans=std::max(ans,data[i]);
    128         }
    129     }
    130     else{
    131         for(int i=l;i<(lb+1)*blockSize;i++){
    132             if(data[i]<key)
    133                 ans=std::max(ans,data[i]);
    134         }
    135         for(int i=rb*blockSize;i<=r;i++){
    136             if(data[i]<key)
    137                 ans=std::max(ans,data[i]);
    138         }
    139         for(int i=lb+1;i<rb;i++){
    140             int pos=std::lower_bound(block[i],block[i]+blockSize,key)-block[i];
    141             if(pos>0)
    142                 ans=std::max(ans,block[i][pos-1]);
    143         }
    144     }
    145     return ans;
    146 }
    147 
    148 inline int Successor(int l,int r,int key){
    149     int lb=l/blockSize;
    150     int rb=r/blockSize;
    151     int ans=INF;
    152     if(lb==rb){
    153         for(int i=l;i<=r;i++)
    154             if(data[i]>key)
    155                 ans=std::min(ans,data[i]);
    156     }
    157     else{
    158         for(int i=l;i<(lb+1)*blockSize;i++){
    159             if(data[i]>key)
    160                 ans=std::min(ans,data[i]);
    161         }
    162         for(int i=rb*blockSize;i<=r;i++){
    163             if(data[i]>key)
    164                 ans=std::min(ans,data[i]);
    165         }
    166         for(int i=lb+1;i<rb;i++){
    167             int pos=std::upper_bound(block[i],block[i]+blockSize,key)-block[i];
    168             if(pos<blockSize)
    169                 ans=std::min(ans,block[i][pos]);
    170         }
    171     }
    172     return ans;
    173 }
    174 
    175 void Initialize(){
    176 #ifndef ASC_LOCAL
    177     freopen("psh.in","r",stdin);
    178     freopen("psh.out","w",stdout);
    179 #endif
    180     FastRead(n);
    181     FastRead(m);
    182     blockSize=sqrt(n);
    183     for(int i=0;i<n;i++){
    184         FastRead(data[i]);
    185         block[blockNum][endSize]=data[i];
    186         if(++endSize==blockSize){
    187             blockNum++;
    188             endSize=0;
    189         }
    190     }
    191     for(int i=0;i<blockNum;i++)
    192         std::sort(block[i],block[i]+blockSize);
    193     if(endSize!=0)
    194         std::sort(block[blockNum],block[blockNum]+endSize);
    195 }
    196 
    197 inline void FastRead(int& target){
    198     target=0;
    199     register char ch=getchar();
    200     bool neg=false;
    201     while(!isdigit(ch)){
    202         if(ch=='-')
    203             neg=true;
    204         ch=getchar();
    205     }
    206     while(isdigit(ch)){
    207         target=target*10+ch-'0';
    208         ch=getchar();
    209     }
    210     if(neg)
    211         target=-target;
    212 }
    Backup: Block Search

    然后图包时间233(拿图至少评论一下吼不吼哇QwQ)

  • 相关阅读:
    堆得简单介绍以及堆排序
    从交换两个变量的值来看程序员的“奇技淫巧”
    两道有意思的题目
    mac上使用brew
    安全考虑,binlog_row_image建议尽量使用FULL
    Python3.6新特性
    自动化测试基础篇--Selenium浏览器操作
    自动化测试基础篇--Selenium Xpath定位
    自动化测试基础篇--Selenium元素定位
    自动化测试基础篇--Selenium Python环境搭建
  • 原文地址:https://www.cnblogs.com/rvalue/p/7212005.html
Copyright © 2020-2023  润新知