• 解题:BZOJ 2989 数列


    题面

    学习二进制分组

    题目本身可以看成二维平面上的问题,转成切比雪夫距离后就是矩形和了

    二进制分组是将每个修改添加到末尾,然后从后往前二进制下进位合并,这样最多同时有$log n$组,每个修改只会被合并$log n$次。再用一个$log$代价在每次询问时把答案合并起来即可

     1 #include<cstdio>
     2 #include<vector>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define vpii vector<pair<int,int> >
     6 using namespace std;
     7 const int N=150005,M=1e7,K=20,inf=1e9;
     8 int n,m,nm,t1,t2,pt,pw,a[N],bin[M+70],vis[M+70];
     9 int root[K][N],val[M+70],son[M+70][2]; vpii ve[20];
    10 char rd[10];
    11 void Modify(int &nde,int lst,int l,int r,int tsk)
    12 {
    13     nde=bin[pt--],vis[nde]=false;
    14     val[nde]=val[lst]+1;
    15     son[nde][0]=son[lst][0];
    16     son[nde][1]=son[lst][1];
    17     if(l==r) return; int mid=(l+r)>>1;
    18     if(tsk<=mid) Modify(son[nde][0],son[lst][0],l,mid,tsk);
    19     else Modify(son[nde][1],son[lst][1],mid+1,r,tsk);
    20 }
    21 void Delete(int nde,int l,int r)
    22 {
    23     if(vis[nde]) return;
    24     bin[++pt]=nde,vis[nde]=true;
    25     int mid=(l+r)>>1;
    26     Delete(son[nde][0],l,mid);
    27     Delete(son[nde][1],mid+1,r);
    28     val[nde]=son[nde][0]=son[nde][1]=0;
    29 }
    30 void Insert(int x,int y)
    31 { 
    32     ve[++pw].push_back(make_pair(x,y));
    33     Modify(root[pw][1],root[pw][0],1,nm,y);
    34     while(pw>1&&ve[pw].size()==ve[pw-1].size())
    35     {
    36         int t1=0,t2=0,sz=ve[pw].size(); vpii tmp;
    37         for(int i=1;i<=sz;i++) Delete(root[pw][i],1,nm);
    38         for(int i=1;i<=sz;i++) Delete(root[pw-1][i],1,nm);
    39         while(t1<sz||t2<sz)
    40             if(t1<sz&&(t2==sz||ve[pw-1][t1]<ve[pw][t2]))
    41                 tmp.push_back(ve[pw-1][t1++]),Modify(root[pw-1][t1+t2],root[pw-1][t1+t2-1],1,nm,ve[pw-1][t1-1].second);
    42             else
    43                 tmp.push_back(ve[pw][t2++]),Modify(root[pw-1][t1+t2],root[pw-1][t1+t2-1],1,nm,ve[pw][t2-1].second);
    44         ve[pw-1]=tmp,ve[pw--].clear();
    45     }
    46 }
    47 int Ask(int nl,int nr,int l,int r,int ll,int rr)
    48 {
    49     if(l>=ll&&r<=rr)
    50         return val[nr]-val[nl];
    51     else
    52     {
    53         int ret=0,mid=(l+r)>>1;
    54         if(mid>=ll) ret+=Ask(son[nl][0],son[nr][0],l,mid,ll,rr);
    55         if(mid<rr) ret+=Ask(son[nl][1],son[nr][1],mid+1,r,ll,rr);
    56         return ret;
    57     }
    58 }
    59 int Query(int x,int y,int k)
    60 {
    61     int ret=0;
    62     for(int i=1;i<=pw;i++)
    63     {
    64         int ll=lower_bound(ve[i].begin(),ve[i].end(),make_pair(x-k,0))-ve[i].begin();
    65         int rr=lower_bound(ve[i].begin(),ve[i].end(),make_pair(x+k,inf))-ve[i].begin();
    66         ret+=Ask(root[i][ll],root[i][rr],1,nm,max(y-k,1),min(y+k,nm));
    67     }
    68     return ret;
    69 }
    70 int main()
    71 {
    72     scanf("%d%d",&n,&m);
    73     vis[0]=true,nm=160000;
    74     for(int i=1;i<=M;i++)
    75         bin[++pt]=i,vis[i]=true; 
    76     for(int i=1;i<=n;i++)    
    77         scanf("%d",&a[i]),Insert(a[i]+i,a[i]-i+n);
    78     for(int i=1;i<=m;i++)
    79     {
    80         scanf("%s%d%d",rd,&t1,&t2);
    81         if(rd[0]=='M') a[t1]=t2,Insert(t2+t1,t2-t1+n);
    82         else printf("%d
    ",Query(a[t1]+t1,a[t1]-t1+n,t2));
    83     }
    84     return 0;
    85 }
    View Code
  • 相关阅读:
    从头编写 asp.net core 2.0 web api 基础框架 (1)
    希腊字母表
    Python数据分析(二): Numpy技巧 (4/4)
    Python数据分析(二): Numpy技巧 (3/4)
    Python数据分析(二): Numpy技巧 (2/4)
    OLED液晶屏幕(3)串口读取文字并分割
    OLED液晶屏幕(2)取模软件
    OLED液晶屏幕(0)自动获取12ic地址液晶屏幕
    OLED液晶屏幕(1)OLED液晶屏幕ssd1306驱动芯片 arduino运行 ESP8266-07可以 12f不可以
    I2C 连接 12864 OLED 屏幕
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10491818.html
Copyright © 2020-2023  润新知