zoukankan      html  css  js  c++  java
  • 【BZOJ3217】ALOEXT 分块

    题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3217

    分块过掉辣!!!!!!$O(n^{1.5}+q imes sqrt{n})$的分块过掉辣!!

    而且速度贼快内存贼小啊(成功踩到b站第一)

    由于此题需要强制在线的删除或者插入,所以我们基于块状链表分块,在每个块内存储指定区间内的所有数,以及该区间内的最大值和次大值,同时再维护一个由该区间内所有数组成的trie树。

    对于修改一个数,首先在该块的trie数中删除该数(直接伪删),然后再插入,接着更新最大值和次大值。

    对于插入一个数,直接在trie树中插入该数,随后在块状链表中插入,更新最大值和次大值。最后判断是否要将该块拆分(如果要察费直接暴力重构两个块即可)

    对于删除一个数,trie树伪删除+块链删除+更新最大值和次大值。随后判断该块大小是否等于0(为零可以直接删掉这个块了)

    对于查询最大值,首先查询出该区间内的次大值。对于完全包含的块,直接将该值丢到该块的trie树中求最大值,对于非完全包含的块,直接暴力求即可。

    PS:经过测试,每个块的大小设置为3200最好(达到3200后切成两块1600的)。最初块大小为400,b站上跑了15.5s,把块大小改为3200后变成3.8s,直接rank1了。

    UPD:前段时间被卡到第二,后来重新把块大小调整为2620,并且加上fread与fwrite,卡到3312ms,重回rank1。

    (不知能否继续优化.....)

      1 #include<bits/stdc++.h>
      2 #define M 5000000
      3 #define N 100
      4 using namespace std;
      5 struct trie{
      6     int a[2],sum;
      7 }p[M]; int uset=0;
      8 int add(int now,int x,int px){
      9     if(!now) now=++uset; 
     10     int ret=now;
     11     for(int i=19;i>=0;i--){
     12         bool k=x&(1<<i); p[now].sum+=px;
     13         if(p[now].a[k]) now=p[now].a[k];
     14         else uset++,p[now].a[k]=uset,now=uset;
     15     }
     16     p[now].sum+=px; 
     17     return ret;
     18 }
     19 int getmax(int now,int x){
     20     int ans=0; 
     21     for(int i=19;i>=0;i--){
     22         bool k=x&(1<<i); 
     23         if(p[p[now].a[1-k]].sum) 
     24         now=p[now].a[1-k],ans+=(1<<i);
     25         else now=p[now].a[k];
     26     }
     27     return ans;
     28 }
     29 struct kuai{
     30     int rt,use,next;
     31     int max1,max2,a[N*4+1];
     32     kuai(){
     33         rt=use=next=max1=max2=0;
     34         memset(a,0,sizeof(a));
     35     }
     36     void getmax(){
     37         max1=max2=0;
     38         for(int i=1;i<=use;i++)
     39         if(a[i]>max1) max2=max1,max1=a[i];
     40         else if(a[i]>max2) max2=a[i];
     41     }
     42 }a[N*7]; int use=1;
     43 void updata(int id,int zhi){
     44     for(int i=1;i;i=a[i].next) 
     45     if(a[i].use>=id){
     46         int last=a[i].a[id]; a[i].a[id]=zhi;
     47         a[i].rt=add(a[i].rt,last,-1);
     48         add(a[i].rt,zhi,1);
     49         a[i].getmax();
     50         return;
     51     }else id-=a[i].use;
     52 }
     53 void cut(int i){
     54     int j=++use;
     55     a[i].use=a[j].use=N*2;
     56     a[j].next=a[i].next; a[i].next=j;
     57     for(int k=1;k<=N*2;k++) 
     58     a[j].a[k]=a[i].a[k+N*2],a[i].a[k+N*2]=0;
     59     a[i].max1=a[i].max2=0;
     60     a[i].getmax(); a[j].getmax();
     61     a[i].rt=add(0,a[i].a[1],1);
     62     a[j].rt=add(0,a[j].a[1],1);
     63     for(int k=2;k<=N*2;k++){
     64         add(a[i].rt,a[i].a[k],1);
     65         add(a[j].rt,a[j].a[k],1);
     66     }
     67 }
     68 void insert(int x,int id){
     69     int i,pre; 
     70     for(i=1;i;pre=i,i=a[i].next) 
     71     if(a[i].use<id) id-=a[i].use;
     72     else break;
     73     if(!i) i=pre,id+=a[i].use;
     74     for(int j=a[i].use;j>=id;j--) a[i].a[j+1]=a[i].a[j];
     75     a[i].a[id]=x; a[i].use++;
     76     a[i].rt=add(a[i].rt,x,1);
     77     if(x>a[i].max1) a[i].max2=a[i].max1,a[i].max1=x;
     78     else if(x>a[i].max2) a[i].max2=x;
     79     if(a[i].use>=N*4) cut(i);
     80 }
     81 void del(int id){
     82     int i,pre=1,x;
     83     for(i=1;i;pre=i,i=a[i].next) 
     84     if(a[i].use<id) id-=a[i].use;
     85     else break;
     86     x=a[i].a[id]; add(a[i].rt,x,-1);
     87     for(int j=id;j<=a[i].use;j++) a[i].a[j]=a[i].a[j+1];
     88     a[i].use--; 
     89     if(a[i].use==0) {a[pre].next=a[i].next; return;}
     90     if(a[i].max2>x) return;
     91     a[i].getmax();
     92 }
     93 int getmax2(int l,int r){
     94     int max1=0,max2=0,sum=0;
     95     int i,pre;
     96     for(i=1;i;pre=i,i=a[i].next){
     97         if(l<=sum+1&&sum+a[i].use<=r){
     98             if(a[i].max1>max1) max2=max1,max1=a[i].max1;
     99             else if(a[i].max1>max2) max2=a[i].max1;
    100             if(a[i].max2>max2) max2=a[i].max2; 
    101         }
    102         else if(sum+1<=l&&r<=sum+a[i].use){
    103             for(int j=l-sum;j<=r-sum;j++)
    104             if(a[i].a[j]>max1) max2=max1,max1=a[i].a[j];
    105             else if(a[i].a[j]>max2) max2=a[i].a[j];
    106         }
    107         else if(sum+1<=l&&l<=sum+a[i].use){
    108             for(int j=l-sum;j<=a[i].use;j++)
    109             if(a[i].a[j]>max1) max2=max1,max1=a[i].a[j];
    110             else if(a[i].a[j]>max2) max2=a[i].a[j];
    111         }
    112         else if(sum+1<=r&&r<=sum+a[i].use){
    113             for(int j=1;j<=r-sum;j++)
    114             if(a[i].a[j]>max1) max2=max1,max1=a[i].a[j];
    115             else if(a[i].a[j]>max2) max2=a[i].a[j];
    116         }
    117         sum+=a[i].use;
    118     }
    119     return max2;
    120 }
    121 int query(int l,int r){
    122     int x=getmax2(l,r),maxn=0,sum=0;
    123     int i,pre;
    124     for(i=1;i;pre=i,i=a[i].next){
    125         if(l<=sum+1&&sum+a[i].use<=r){
    126             maxn=max(maxn,getmax(a[i].rt,x));
    127         }
    128         else if(sum+1<=l&&r<=sum+a[i].use){
    129             for(int j=l-sum;j<=r-sum;j++)
    130             maxn=max(maxn,x^a[i].a[j]);
    131         }
    132         else if(sum+1<=l&&l<=sum+a[i].use){
    133             for(int j=l-sum;j<=a[i].use;j++)
    134             maxn=max(maxn,x^a[i].a[j]);
    135         }
    136         else if(sum+1<=r&&r<=sum+a[i].use){
    137             for(int j=1;j<=r-sum;j++)
    138             maxn=max(maxn,x^a[i].a[j]);
    139         }
    140         sum+=a[i].use;
    141     }
    142     return maxn;
    143 }
    144 int main(){
    145     int n,m,lastans=0,n0;
    146     scanf("%d%d",&n,&m); n0=n;
    147     for(int i=1;i<=n;i++){
    148         int x; scanf("%d",&x);
    149         insert(x,i);
    150     }
    151     while(m--){
    152         char c[10]; int x,y;
    153         scanf("%s%d",c,&x);
    154         x=(x+lastans)%n0+1;
    155         if(c[0]=='D'){del(x); n0--;continue;}
    156         scanf("%d",&y);
    157         if(c[0]=='F') y=(y+lastans)%n0+1;
    158         else y=(y+lastans)%1048576;
    159         if(c[0]=='I') insert(y,x),n0++;
    160         if(c[0]=='C') updata(x,y);
    161         if(c[0]=='F') printf("%d
    ",lastans=query(min(x,y),max(x,y)));
    162     }
    163 }
  • 相关阅读:
    div3--C. Pipes
    Problem F Free Weights
    H
    Problem C Careful Ascent
    Problem L. World Cup
    Problem E. Bet
    Problem D. Ice Cream Tower
    A. Number Theory Problem
    A
    软考知识点梳理--项目评估
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7900131.html
Copyright © 2011-2022 走看看