zoukankan      html  css  js  c++  java
  • LOJ #6282. 数列分块入门 6

    单点插入,单点查询。

    因为要么插入O(1)查询O(sqrt(n)),要么插入O(sqrt(n)),查询O(1),所以选择代码难度更小的非链表暴力后移。

    但是直接这样做虽然在随机数据上表现不错,但是在那些特意构造出的在某个区间疯狂加点的数据上会退化到与暴力差不多。

    解决办法是每sqrt(n)次insert后将块重构,增大一点常数但使其保持均衡,从而保证复杂度不会被卡。

     1 #include<iostream>
     2 #include<cmath>
     3 #include<vector>
     4 #include<cstdio>
     5 using namespace std;
     6 
     7 void read(int& a){
     8     a = 0;char c = getchar(),l = c;
     9     while(c < '0'||c > '9')l = c,c = getchar();
    10     while('0' <= c&&c <= '9')a = a*10+c-'0',c = getchar();
    11     if(l == '-')a *= -1;
    12 }
    13 
    14 vector<int> ve[350];
    15 int n,blo,cnti;
    16 
    17 void insert(int x,int pl){
    18     int suf,p;
    19     for(suf = 0,p = 1;suf+ve[p].size() < pl;p++)
    20         suf += ve[p].size();
    21     pl -= suf+1;int y = *--ve[p].end();
    22     ve[p].push_back(y);
    23     for(register int i = ve[p].size()-2;i > pl;i--)ve[p][i] = ve[p][i-1];
    24     ve[p][pl] = x;
    25 }
    26 
    27 int ask(int r){
    28     int suf,p;
    29     for(suf = 0,p = 1;suf+ve[p].size() < r;p++)
    30         suf += ve[p].size();
    31     return ve[p][r-suf-1];
    32 }
    33 
    34 vector<int> all;
    35 void reset(){
    36     all.clear();
    37     for(int i = 1;i <= (n-1)/blo+1;i++){
    38         for(int j = 0;j < ve[i].size();j++)
    39             all.push_back(ve[i][j]);
    40         ve[i].clear();
    41     }
    42     n = all.size(),blo = sqrt(n);
    43     for(int i = 0;i < n;i++)
    44         ve[i/blo+1].push_back(all[i]);
    45 }
    46 
    47 int main(){
    48     read(n); blo = sqrt(n);
    49     for(register int i = 1;i <= n;i++){
    50         int x; read(x);
    51         ve[(i-1)/blo+1].push_back(x);
    52     }
    53     for(register int i = n;i > 0;i--){
    54         int opt,l,r,c;
    55         read(opt),read(l),read(r),read(c);
    56         switch(opt){
    57             case 0:
    58                 insert(r,l); cnti++;
    59                 if(cnti%blo == 0)reset();
    60             break;
    61             case 1:
    62                 printf("%d
    ",ask(r));
    63             break;
    64         }
    65     }
    66 return 0;
    67 }
  • 相关阅读:
    怎么对Navicat for Oracle 调试
    老版本的java代码与新代码如何找出差异
    Oracle 外部表是做什么用的
    如何在Navicat 中编辑和记录
    如何使用文件对比工具文件夹比较会话菜单
    哪些工具可以用来进行Bug管理
    5类开发者须知的工具
    怎么找出代码之间的差异
    Beyond Compare不仅可以修改网页代码
    文件对比工具有哪些用途
  • 原文地址:https://www.cnblogs.com/Wangsheng5/p/11785321.html
Copyright © 2011-2022 走看看