zoukankan      html  css  js  c++  java
  • [Comet1173]最简单的题

    称区间$[l,r]$的"信息"为其的答案和第一个、最后一个大于$x$的位置,显然通过$[l,mid]$和$[mid+1,r]$的信息可以$o(1)$合并得到$[l,r]$的信息

    考虑分块,将其按$K$的块大小分块,区间查询时求出散块每一个位置的信息(将其看作一个区间)和每一个整块的信息,之后即可$o(K+frac{n}{K})$合并得到整个块的信息

    下面的问题即如何求整块的信息,对整块维护:1.排序后的结果;2.当$x$为块中每一个元素时的信息;3.[luogu6466]分散层叠算法的做法4所维护的分治结构(将$x$作为小于等于$x$的最大元素即可)

    对于排序后的结果时间复杂度为$o(nlog n)-o(K)$(单点修改即插入排序),当得到排序后的结果后,该块的"信息"也可以在$o(K)$的复杂度内得到——

    关于答案,只需要从小到大枚举元素,每一次即加入一个元素,通过链表支持合并即可

    关于第一个和最后一个大于$x$的位置,维护排序后的序列位置的后缀最小值和最大值即可

    由此即可支持单点修改,单次复杂度为$o(K)$,取$K=sqrt{n}$单次复杂度即$o(sqrt{n})$

    时间复杂度为$o(nlog n)-o(sqrt{n})$

    (由于该oj似乎不支持提交,与某个通过的代码拍过,正确性大概是能保证的,速度大约是其1.5倍)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 300005
      4 #define K 600
      5 #define D 3
      6 #define ll long long
      7 #define L (k<<1)
      8 #define R (L+1)
      9 #define mid (l+r>>1)
     10 struct Data{
     11     int l,r;
     12     ll ans;
     13 }ans[N];
     14 int n,m,k,p,x,y,z,num[21],a[N],bl[N],st[K],ed[K],id[N];
     15 int read(){
     16     int x=0;
     17     char c=getchar();
     18     while ((c<'0')||(c>'9'))c=getchar();
     19     while ((c>='0')&&(c<='9')){
     20         x=x*10+(c-'0');
     21         c=getchar();
     22     }
     23     return x;
     24 }
     25 void write(ll x,char c=''){
     26     while (x){
     27         num[++num[0]]=x%10;
     28         x/=10;
     29     }
     30     if (!num[0])putchar('0');
     31     while (num[0])putchar(num[num[0]--]+'0');
     32     putchar(c);
     33 }
     34 bool cmp(int x,int y){
     35     return a[x]<a[y];
     36 }
     37 bool Cmp(int x,int y){
     38     return a[x]<=y;
     39 }
     40 Data merge(Data x,Data y);
     41 namespace Rope{
     42     int n,vis[N],l[N],r[N];
     43     ll ans;
     44     void init(int nn){
     45         n=nn;
     46         for(int i=0;i<=n+1;i++)vis[i]=0;
     47         for(int i=1;i<=n;i++)l[i]=r[i]=i;
     48     }
     49     void link(int x){
     50         ans+=(ll)(x-l[x]+1)*(r[x+1]-x);
     51         l[r[x+1]]=l[x],r[l[x]]=r[x+1];
     52     }
     53     ll add(int x){
     54         ans=vis[x]=1;
     55         if (vis[x-1])link(x-1);
     56         if (vis[x+1])link(x);
     57         return ans;
     58     }
     59 };
     60 namespace Seg{
     61     int Pos[2],b[K<<2][K],pos[K<<2][K][2];
     62     void get(int k,int x){
     63         b[k][0]=0;
     64         for(int i=st[x];i<=ed[x];i++)b[k][++b[k][0]]=id[i];
     65     }
     66     void up(int k){
     67         b[k][0]=0;
     68         int x=1,y=1;
     69         while ((x<=b[L][0])||(y<=b[R][0])){
     70             if ((x<=b[L][0])&&((y>b[R][0])||(cmp(b[L][x],b[R][y])))){
     71                 b[k][++b[k][0]]=b[L][x];
     72                 pos[k][b[k][0]][0]=x;
     73                 pos[k][b[k][0]][1]=0;
     74                 x+=D;
     75             }
     76             else{
     77                 b[k][++b[k][0]]=b[R][y];
     78                 pos[k][b[k][0]][0]=0;
     79                 pos[k][b[k][0]][1]=y;
     80                 y+=D;
     81             }
     82         }
     83         memset(Pos,0,sizeof(Pos));
     84         for(int i=1;i<=b[k][0];i++)
     85             for(int p=0;p<2;p++){
     86             if (pos[k][i][p])Pos[p]=pos[k][i][p];
     87             pos[k][i][p]=Pos[p];
     88         }
     89     }
     90     void build(int k,int l,int r){
     91         if (l==r){
     92             get(k,l);
     93             return;
     94         }
     95         build(L,l,mid);
     96         build(R,mid+1,r);
     97         up(k);
     98     }
     99     void update_point(int k,int l,int r,int x){
    100         if (l==r){
    101             get(k,x);
    102             return;
    103         }
    104         if (x<=mid)update_point(L,l,mid,x);
    105         else update_point(R,mid+1,r,x);
    106         up(k);
    107     }
    108     void query_seg(int k,int l,int r,int x,int y,int z,int w){
    109         if ((l>y)||(x>r))return;
    110         if (!z){
    111             ans[0]=merge(ans[0],Data{0,0,0});
    112             return;
    113         }
    114         if (l==r){
    115             ans[0]=merge(ans[0],ans[b[k][z]]);
    116             return;
    117         }
    118         int zl=pos[k][z][0],zr=pos[k][z][1];
    119         while ((zl<b[L][0])&&(Cmp(b[L][zl+1],w)))zl++;
    120         while ((zr<b[R][0])&&(Cmp(b[R][zr+1],w)))zr++;
    121         query_seg(L,l,mid,x,y,zl,w);
    122         query_seg(R,mid+1,r,x,y,zr,w);
    123     }
    124     void query(int l,int r,int x){
    125         if (l>r)return;
    126         query_seg(1,1,bl[n],l,r,lower_bound(b[1]+1,b[1]+b[1][0]+1,x,Cmp)-b[1]-1,x);
    127     }
    128 };
    129 Data merge(Data x,Data y){
    130     Data ans;
    131     ans.ans=x.ans+y.ans;
    132     if ((x.r<0)&&(y.r<0)){
    133         ans.l=x.l+y.l,ans.r=-1;
    134         ans.ans+=(ll)x.l*y.l;
    135         return ans;
    136     }
    137     if (x.r<0){
    138         ans.l=x.l+y.l,ans.r=y.r;
    139         ans.ans+=(ll)x.l*y.l;
    140         return ans;
    141     }
    142     if (y.r<0){
    143         ans.l=x.l,ans.r=x.r+y.l;
    144         ans.ans+=(ll)x.r*y.l;
    145         return ans;
    146     }
    147     ans.l=x.l,ans.r=y.r;
    148     ans.ans+=(ll)x.r*y.l;
    149     return ans;
    150 }
    151 void upd(int k,int x){
    152     for(int i=st[k];i<=ed[k];i++)
    153         if (id[i]==x){
    154             x=i;
    155             break;
    156         }
    157     int s=id[x];
    158     for(int i=x;i<ed[k];i++)id[i]=id[i+1];
    159     for(int i=st[k];i<ed[k];i++)
    160         if (cmp(s,id[i])){
    161             for(int j=ed[k];j>i;j--)id[j]=id[j-1];
    162             id[i]=s;
    163             return;
    164         }
    165     id[ed[k]]=s;
    166 }
    167 void calc(int k){
    168     ans[id[ed[k]]].l=ed[k]-st[k]+1,ans[id[ed[k]]].r=-1;
    169     int l=id[ed[k]]-st[k],r=ed[k]-id[ed[k]];
    170     for(int i=ed[k]-1;i>=st[k];i--){
    171         ans[id[i]].l=l,ans[id[i]].r=r;
    172         l=min(l,id[i]-st[k]),r=min(r,ed[k]-id[i]);
    173     }
    174     Rope::init(ed[k]-st[k]+1);
    175     ll sum=0;
    176     for(int i=st[k];i<=ed[k];i++){
    177         sum+=Rope::add(id[i]-st[k]+1);
    178         ans[id[i]].ans=sum;
    179     }
    180 }
    181 int main(){
    182     n=read(),m=read(),k=(int)sqrt(n);
    183     for(int i=1;i<=n;i++)a[i]=read();
    184     for(int i=1;i<=n;i++){
    185         id[i]=i;
    186         bl[i]=(i-1)/k+1;
    187         if (!st[bl[i]])st[bl[i]]=i;
    188         ed[bl[i]]=i;
    189     }
    190     for(int i=1;i<=bl[n];i++){
    191         sort(id+st[i],id+ed[i]+1,cmp);
    192         calc(i);
    193     }
    194     Seg::build(1,1,bl[n]);
    195     for(int i=1;i<=m;i++){
    196         p=read(),x=read(),y=read();
    197         if (p==1){
    198             a[x]=y;
    199             upd(bl[x],x);
    200             calc(bl[x]);
    201             Seg::update_point(1,1,bl[n],bl[x]);
    202         }
    203         else{
    204             z=read();
    205             ans[0]=Data{0,-1,0};
    206             if (bl[x]==bl[y]){
    207                 for(int j=x;j<=y;j++)
    208                     if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
    209                     else ans[0]=merge(ans[0],Data{1,-1,1});
    210             }
    211             else{
    212                 for(int j=x;j<=ed[bl[x]];j++)
    213                     if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
    214                     else ans[0]=merge(ans[0],Data{1,-1,1});
    215                 Seg::query(bl[x]+1,bl[y]-1,z);
    216                 for(int j=st[bl[y]];j<=y;j++)
    217                     if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
    218                     else ans[0]=merge(ans[0],Data{1,-1,1});
    219             }
    220             write(ans[0].ans,'
    ');
    221         }
    222     }
    223     return 0;
    224 } 
    View Code
  • 相关阅读:
    5 TensorFlow入门笔记之RNN实现手写数字识别
    用python简便地抓取刘昊然的写真(17行代码)
    MFC实现简单飞机大战(含游戏声音)
    4 TensorFlow入门之dropout解决overfitting问题
    3 TensorFlow入门之识别手写数字
    2 TensorFlow入门笔记之建造神经网络并将结果可视化
    1 TensorFlow入门笔记之基础架构
    用python的turtle画分形树
    win10下安装TensorFlow(CPU only)
    python中math常用函数
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15236688.html
Copyright © 2011-2022 走看看