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
  • 相关阅读:
    jQuery 基本选择器
    JavaScriptif while for switch流程控制 JS函数 内置对象
    JavaScrip基本语法
    数据库 存储引擎 表的操作 数值类型 时间类型 字符串类型 枚举集合 约束
    数据库基础知识 管理员 用户登录授权的操作
    粘包的产生原理 以及如何解决粘包问题
    socket TCP DPT 网络编程
    2018年年终总结
    Android技术分享
    No accelerator found
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15236688.html
Copyright © 2011-2022 走看看