• 阴间分块:区间赋值,单点查询(分块套分块)


    czyarl:https://www.cnblogs.com/czyarl/p/14515009.html

    题目大意:有一个长度为n的序列,初始全为0。有两种操作:第一种是区间赋值,并且值全为正数且单调增;第二种是询问一个位置的值是什么。

    所有的操作都是由程序在运行中根据seed随机生成的。也就是说,你可以无视入读带来的常数影响。

    n的长度:6250000

    操作1的次数:20000000

    操作2的次数:10000

    时间限制:8s

    空间:1024Mb

    思考:这道题的前身是某道题中的分块部分,但它只需要支持前后缀修改,单点查询。在czyarl冷静思考过后,想到了这个能支持O(1)区间修改,O(sqrt(n))单点查询(但常数很大,被zkw几近乱杀且用途很狭窄)的分块做法。(不过好像还没有见到任何一道题用过这个技巧)

    我们先考虑这样一种分块,它建立在长度为n的序列上,支持O(1)区间修改,O(n)单点询问。首先,我们将其分为根号个块,并且对每个块开一个大小为$size_i*size_i$的二维数组tag[][]用来记录修改的信息,其中size是这一个块的大小。其次,我们继续开一个大小为$sqrt{n}*sqrt{n}$的二维数组tagB[][],用来保存对于整块修改的信息。

    对于一次修改操作,如果修改的区间完全落入一个块内,那么就在对应的tag[l][r]上进行一次更新。如果它跨过了若干区间,我们先在对应的左右块的tag[][]上进行一次更新,接着在tagB[cl][cr]上进行更新,其中cl、cr分别为l所属块的编号+1、r所属块的编号-1。

    对于一次询问操作,我们先定位到所属的块,接着花$size_i*size_i$的时间询问这个块内tag[][]的答案。还有一些对整块进行修改的操作,花$sqrt{n}*sqrt{n}$的时间询问tagB[][]的答案。这样,我们就做到了O(1)区间修改和O(n)单点查询。这个数据结构的空间是O(n^1.5)的。

    回到原问题上,我们先对原始的序列进行分块,并对每一个块使用一个上述的数据结构。如果一次修改完全落入一个块呢,那我们直接对这个块进行上述的修改操作。如果这次修改跨过若干个块,注意到跨过的整块的个数只有$sqrt{n}$个,因此我们再对原数组使用一个上述的数据结构,用来记录修改整块的信息。

    对于一次询问,我们先定位到所属的块,得到这个块内的答案。接着,我们再询问整块的答案,就得到了想要的东西。

    于是,就做到了O(1)修改和O(sqrt(n))询问,空间复杂度是O(n^1.25)的(因为用了根号个上述的数据结构,每个数据结构的长度是n^0.5,n^0.75*n^0.5=n^1.25)。

    优化:我们发现一次修改最坏要改9次数组,而其中有两次实际上只有前后缀修改。对于前后缀修改,我们只要在相应位置记录下答案,在询问时去找就行了。

    czy代码:

      1 #include<bits/stdc++.h>
      2 #define LL long long
      3 #define MAXN 2560100
      4 #define MAXSQR1 2560100
      5 #define MAXSQR2 1610
      6 #define MAXSQR4 41
      7 #define INF 1010000000
      8 using namespace std;
      9 template<typename T> void Read(T &cn)
     10 {
     11     char c; int sig = 1;
     12     while(!isdigit(c = getchar())) if(c == '-') sig = 0;
     13     if(sig) {cn = c-48; while(isdigit(c = getchar())) cn = cn*10-48+c; }
     14     else    {cn = 48-c; while(isdigit(c = getchar())) cn = cn*10+48-c; }
     15 }
     16 template<typename T> void Write(T cn)
     17 {
     18     T cm = 0; int cx = cn%10, wei = 0; cn = cn/10;
     19     if(cn < 0 || cx < 0) {putchar('-'); cn = -cn; cx = -cx; }
     20     while(cn) wei++, cm = cm*10+cn%10, cn = cn/10;
     21     while(wei--) putchar(cm%10+48), cm = cm/10;
     22     putchar(cx+48);
     23 }
     24 template<typename T> void WriteS(T cn) {Write(cn); putchar(' '); }
     25 template<typename T> void WriteL(T cn) {Write(cn); puts(""); }
     26 namespace getNum{
     27     unsigned lst;
     28     int q1, q2, A, n;
     29     void pre(int cn, int cq1, int cq2, int seed, int cA) {q1 = cq1, q2 = cq2, lst = seed, A = cA, n = cn; }
     30     unsigned get_r(unsigned cn) {lst ^= lst<<7; lst ^= lst>>3; lst ^= lst<<13; return lst%cn; }
     31     int get_n(int l, int r) {return l + get_r(r-l+1); }
     32     void get_val(int &val) {val = get_n(1, A); }
     33     void get_ne(int &typ, int &pos, int &l, int &r, int &val)
     34     {
     35         typ = get_n(1, q1+q2)<=q1 ? 1 : 2;
     36         if(typ == 1) q1--, l = get_n(1,n), r = get_n(l, n), val = get_n(1, A);
     37         if(typ == 2) q2--, pos = get_n(1,n);
     38     }
     39 }
     40 template<typename T> void Max(T &cn, T cm) {cn = cn < cm ? cm : cn; }
     41 template<typename T> void Min(T &cn, T cm) {cn = cn < cm ? cn : cm; }
     42 struct Blo4{
     43     int a[MAXSQR4+1][MAXSQR4+1];
     44     int n;
     45     void build(int ca[], int l, int r)
     46     {
     47         n = r-l+1;
     48         for(int i = 1;i<=n;i++) 
     49         {
     50             a[i][i] = ca[l+i-1];
     51             for(int j = i+1;j<=n;j++) a[i][j] = min(a[i][j-1], ca[l+j-1]); 
     52         }
     53     }
     54     void qu_min(int l, int r, int cn) {Min(a[l][r], cn); }
     55     int query(int cn) 
     56     {
     57         int ans = a[cn][cn];
     58         for(int i = 1;i<=cn;i++) for(int j = cn;j<=n;j++) Min(ans, a[i][j]);
     59         return ans;
     60     }
     61 };
     62 struct Blo2{
     63     Blo4 a[MAXSQR4+2];
     64     int pre[MAXSQR2+1], suf[MAXSQR2+1], blo[MAXSQR2+1], tou[MAXSQR2+1], wei[MAXSQR2+1];
     65     int tmp[MAXSQR4+1];
     66     int n, Sqr, alen;
     67     int hav_pre, hav_suf;
     68     void build(int ca[], int l, int r)
     69     {
     70         n = r-l+1; Sqr = sqrt(n);
     71         for(int i = 1;i<=n;i++) pre[i] = suf[i] = INF; hav_pre = hav_suf = 0; 
     72         for(int i = 1;i<=n;)
     73         {
     74             int j = min(n, i+Sqr-1); alen++;
     75             tou[alen] = i; wei[alen] = j;
     76             for(int ij = i;ij<=j;ij++) blo[ij] = alen;
     77             a[alen].build(ca, l+i-1, l+j-1);
     78             tmp[alen] = INF;
     79             i = j+1;
     80         }
     81         ++alen; a[alen].build(tmp, 1, alen-1);
     82     }
     83     void qu_min_suf(int l, int cn) {Min(suf[l], cn), hav_suf = 1; }
     84     void qu_min_pre(int r, int cn) {Min(pre[r], cn), hav_pre = 1; }
     85     void qu_min(int l, int r, int cn)
     86     {
     87         if(blo[l] == blo[r]) a[blo[l]].qu_min(l-tou[blo[l]]+1, r-tou[blo[l]]+1, cn);
     88         else {
     89             a[blo[l]].qu_min(l-tou[blo[l]]+1, wei[blo[l]]-tou[blo[l]]+1, cn);
     90             a[alen].qu_min(blo[l]+1, blo[r]-1, cn);
     91             a[blo[r]].qu_min(1, r-tou[blo[r]]+1, cn);
     92         }
     93     }
     94     int query(int cn) 
     95     {
     96         int ans = min(a[alen].query(blo[cn]), a[blo[cn]].query(cn-tou[blo[cn]]+1));
     97         if(hav_pre) for(int i = cn;i<=n;i++) Min(ans, pre[i]);
     98         if(hav_suf) for(int i = 1;i<=cn;i++) Min(ans, suf[i]);
     99         return ans;
    100     }
    101 };
    102 struct Blo1{
    103     Blo2 a[MAXSQR2+2];
    104     int blo[MAXSQR1+1], tou[MAXSQR1+1], wei[MAXSQR1+1];
    105     int tmp[MAXSQR2+1];
    106     int n, Sqr, alen;
    107     void build(int ca[], int l, int r)
    108     {
    109         n = r-l+1; Sqr = sqrt(n);
    110         for(int i = 1;i<=n;)
    111         {
    112             int j = min(n, i+Sqr-1); alen++;
    113             tou[alen] = i; wei[alen] = j;
    114             for(int ij = i;ij<=j;ij++) blo[ij] = alen;
    115             a[alen].build(ca, l+i-1, l+j-1);
    116             tmp[alen] = INF;
    117             i = j+1;
    118         }
    119         ++alen; a[alen].build(tmp, 1, alen-1);
    120     }
    121     void qu_min(int l, int r, int cn)
    122     {
    123         if(blo[l] == blo[r]) a[blo[l]].qu_min(l-tou[blo[l]]+1, r-tou[blo[l]]+1, cn);
    124         else {
    125             a[blo[l]].qu_min_suf(l-tou[blo[l]]+1, cn);
    126             if(blo[l] < blo[r]-1) a[alen].qu_min(blo[l]+1, blo[r]-1, cn);
    127             a[blo[r]].qu_min_pre(r-tou[blo[r]]+1, cn);
    128         }
    129     }
    130     int query(int cn) {return min(a[alen].query(blo[cn]), a[blo[cn]].query(cn-tou[blo[cn]]+1)); }
    131 };
    132 Blo1 T;
    133 int n, q1, q2, Seed, A;
    134 int a[MAXN+1];
    135 int main()
    136 {
    137     cerr<<(sizeof(T))/1024.0/1024.0<<endl;
    138 //    freopen("block.in","r",stdin);
    139     freopen("block.out","w",stdout);
    140     Read(n); Read(q1); Read(q2); Read(A); Read(Seed);
    141     getNum::pre(n, q1, q2, Seed, A);
    142     for(int i = 1;i<=n;i++) getNum::get_val(a[i]);
    143     T.build(a, 1, n);
    144     LL ans = 0;
    145     for(int i = 1;i<=q1+q2;i++)
    146     {
    147         int btyp, bx, bl, br, bpos; 
    148         getNum::get_ne(btyp, bpos, bl, br, bx);
    149         if(btyp == 1) T.qu_min(bl, br, bx);
    150         if(btyp == 2) ans = ans ^ (1ll*T.query(bpos)*i);
    151     }
    152     WriteL(ans);
    153     return 0;
    154 }
    View Code

    我的代码:(用了vector,修改甚至要改9次,因此慢了4倍)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=3E6+5;
      4 struct info
      5 {
      6     int x;
      7     info(int a=0,int b=0):x(a){}
      8 };
      9 inline void chmax(info&x,const info&y)
     10 {
     11     if(y.x>x.x)
     12         x=y;
     13 }
     14 inline int get(int l,int r,int len)
     15 {
     16     return l*len+r-l*(l+1)/2;
     17 }
     18 struct BLOCK
     19 {
     20     int n,len,totC,bel[1605],size[1605],toL[1605],toR[1605];
     21     vector<info>tag[1605],tagB;
     22     inline void build(int m)
     23     {
     24         n=m;
     25         len=sqrt(n);
     26         bel[0]=1;
     27         ++size[1];
     28         for(int i=1;i<n;++i)
     29         {
     30             bel[i]=bel[i-1]+(i%len==0);
     31             toR[bel[i]]=i;
     32             ++size[bel[i]];
     33         }
     34         for(int i=n-1;i>=0;--i)
     35             toL[bel[i]]=i;
     36         totC=bel[n-1];
     37         for(int i=1;i<=totC;++i)
     38             tag[i].resize((size[i]+1)*size[i]/2);
     39         tagB.resize((totC+1)*totC/2);
     40     }
     41     inline void change(int l,int r,const info&A)
     42     {
     43         int cl=bel[l],cr=bel[r];
     44         if(cl==cr)
     45         {
     46             chmax(tag[cl][get(l-toL[cl],r-toL[cl],size[cl])],A);
     47             return;
     48         }
     49         chmax(tag[cl][get(l-toL[cl],size[cl]-1,size[cl])],A);
     50         chmax(tag[cr][get(0,r-toL[cr],size[cr])],A);
     51         if(cl+1<=cr-1)
     52             chmax(tagB[get(cl+1,cr-1,totC)],A);
     53     }
     54     inline info ask(int pos)
     55     {
     56         info A(0,0);
     57         int c=bel[pos],p=0;
     58         int bias=pos-toL[c];
     59         for(int l=0;l<size[c];++l)
     60             for(int r=l;r<size[c];++r,++p)
     61                 if(l<=bias&&bias<=r)
     62                     chmax(A,tag[c][p]);
     63         p=0;
     64         for(int l=0;l<totC;++l)
     65             for(int r=l;r<totC;++r,++p)
     66                 if(l<=c&&c<=r)
     67                     chmax(A,tagB[p]);
     68         return A;
     69     }
     70 }T1[1605],T2;
     71 int n,len,totC,bel[maxn],toL[maxn],toR[maxn];
     72 inline int ask(int pos)
     73 {
     74     info A=T1[bel[pos]].ask(pos-toL[bel[pos]]);
     75     chmax(A,T2.ask(bel[pos]-1));
     76     return A.x;
     77 }
     78 int TI;
     79 inline void change(int l,int r,int x)
     80 {
     81     info A(x,++TI);
     82     int cl=bel[l],cr=bel[r];
     83     if(cl==cr)
     84         T1[cl].change(l-toL[cl],r-toL[cl],A);
     85     else
     86     {
     87         T1[cl].change(l-toL[cl],toR[cl]-toL[cl],A);
     88         T1[cr].change(0,r-toL[cr],A);
     89         if(cl<=cr-2)
     90             T2.change(cl,cr-2,A);
     91     }
     92 }
     93 int size[maxn];
     94 inline void init()
     95 {
     96     len=sqrt(n);
     97     for(int i=1;i<=n;++i)
     98     {
     99         bel[i]=bel[i-1]+((i-1)%len==0);
    100         toR[bel[i]]=i;
    101         ++size[bel[i]];
    102     }
    103     for(int i=n;i>=1;--i)
    104         toL[bel[i]]=i;
    105     totC=bel[n];
    106     for(int i=1;i<=totC;++i)
    107         T1[i].build(size[i]);
    108     T2.build(totC);
    109 }
    110 mt19937 rd(233);
    111 const int limit=5000;
    112 inline int R(int l,int r)
    113 {
    114     return rd()%(r-l+1)+l;
    115 }
    116 int main()
    117 {
    118     freopen("a.out","w",stdout);
    119     ios::sync_with_stdio(false);
    120     cin>>n;
    121     init();
    122     int T;
    123     cin>>T;
    124     for(int i=1;i<=T;++i)
    125     {
    126         int opt;
    127         if(i%limit==0)
    128             opt=1;
    129         else
    130             opt=0;
    131         if(opt==1)
    132         {
    133             int x=R(1,n);
    134             cout<<ask(x)<<'
    ';
    135         }
    136         else
    137         {
    138             int l=R(1,n),r=R(1,n),x=i;
    139             if(l>r)
    140                 swap(l,r);
    141             change(l,r,x);
    142         }
    143     }
    144     return 0;
    145 }
    View Code

    我的代码:优化了很多很多,但变得不可读了。在n=6250000,T=100000000时比zkw快两倍。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=7E6+5;
      4 int n;
      5 int tot2,tot3[2600],tot5;
      6 int len2,len3[2600],len4,len5;
      7 int bel2[maxn],bel3[maxn],bel5[maxn];
      8 int size2[2600],size3[500000],size5[2600];
      9 int toL2[2600],toR2[2600],toL3[500000],toR3[500000],toL5[2600],toR5[2600];
     10 int tag2[maxn],tag3[maxn*52],tag5[maxn],tag4[maxn];
     11 int bias2[2600],bias3[500000],bias5[500000];
     12 int pre2[maxn],suf2[maxn],pre4[maxn],suf4[maxn];
     13 inline int get(int l,int r,int len)
     14 {
     15     return l*len-l*(l+1)/2+r;
     16 }
     17 inline void init()
     18 {
     19     len2=sqrt(n);
     20     for(int i=1;i<=n;++i)
     21     {
     22         bel2[i]=bel2[i-1]+((i-1)%len2==0);
     23         ++size2[bel2[i]];
     24         toR2[bel2[i]]=i;
     25     }
     26     for(int i=n;i>=1;--i)
     27         toL2[bel2[i]]=i;
     28     tot2=bel2[n];
     29     for(int i=1;i<=tot2;++i)
     30     {
     31         len3[i]=sqrt(size2[i]);
     32         for(int j=toL2[i];j<=toR2[i];++j)
     33         {
     34             bel3[j]=bel3[j-1]+((j-toL2[i])%len3[i]==0);
     35             ++size3[bel3[j]];
     36             toR3[bel3[j]]=j;
     37         }
     38         for(int j=toR2[i];j>=toL2[i];--j)
     39             toL3[bel3[j]]=j;
     40         tot3[i]=bel3[toR2[i]]-bel3[toL2[i]]+1;
     41         bias2[i]=bias2[i-1]+(tot3[i]+1)*tot3[i]/2;
     42     }
     43     for(int i=1;i<=bel3[n];++i)
     44         bias3[i]=bias3[i-1]+(size3[i]+1)*size3[i]/2;
     45     len4=tot2;
     46     len5=sqrt(tot2);
     47     for(int i=1;i<=tot2;++i)
     48     {
     49         bel5[i]=bel5[i-1]+((i-1)%len5==0);
     50         ++size5[bel5[i]];
     51         toR5[bel5[i]]=i;
     52     }
     53     for(int i=tot2;i>=1;--i)
     54         toL5[bel5[i]]=i;
     55     tot5=bel5[tot2];
     56     for(int i=1;i<=tot5;++i)
     57         bias5[i]=bias5[i-1]+(size5[i]+1)*size5[i]/2;
     58         /*
     59     for(int i=1;i<=n;++i)
     60         cout<<bel2[i]<<" ";cout<<endl;
     61     for(int i=1;i<=n;++i)
     62         cout<<bel3[i]<<" ";cout<<endl;
     63     for(int i=1;i<=tot2;++i)
     64         cout<<bel5[i]<<" ";cout<<endl;
     65     for(int i=1;i<=bel3[n];++i)
     66         cout<<toL3[i]<<" ";cout<<endl;*/
     67 }
     68 inline void chmax(int&x,int y)
     69 {
     70     x=max(x,y);
     71 }
     72 inline int ask(int pos)
     73 {
     74     int x=0;
     75     int p=0;
     76     int c3=bel3[pos];
     77     for(int l=toL3[c3];l<=toR3[c3];++l)
     78         for(int r=l;r<=toR3[c3];++r,++p)
     79             if(l<=pos&&pos<=r)
     80                 chmax(x,tag3[bias3[c3-1]+p]);
     81     p=0;
     82     int c2=bel2[pos];
     83     for(int l=bel3[toL2[c2]];l<=bel3[toR2[c2]];++l)
     84         for(int r=l;r<=bel3[toR2[c2]];++r,++p)
     85             if(l<=c3&&c3<=r)
     86                 chmax(x,tag2[bias2[c2-1]+p]);
     87     for(int i=pos;bel2[i]==c2;--i)
     88         chmax(x,suf2[i]);
     89     for(int i=pos;bel2[i]==c2;++i)
     90         chmax(x,pre2[i]);
     91     p=0;
     92     int c5=bel5[c2];
     93     for(int l=toL5[c5];l<=toR5[c5];++l)
     94         for(int r=l;r<=toR5[c5];++r,++p)
     95             if(l<=c2&&c2<=r)
     96                 chmax(x,tag5[bias5[c5-1]+p]);
     97     p=0;
     98     for(int l=1;l<=tot5;++l)
     99         for(int r=l;r<=tot5;++r,++p)
    100             if(l<=c5&&c5<=r)
    101                 chmax(x,tag4[p]);
    102     for(int i=c2;bel5[i]==c5;--i)
    103         chmax(x,suf4[i]);
    104     for(int i=c2;bel5[i]==c5;++i)
    105         chmax(x,pre4[i]);
    106     return x;
    107 }
    108 inline void change(int l,int r,int x)
    109 {
    110     int cl2=bel2[l],cr2=bel2[r];
    111     if(cl2==cr2)
    112     {
    113         int cl3=bel3[l],cr3=bel3[r];
    114         if(cl3==cr3)
    115         {
    116             tag3[bias3[cl3-1]+get(l-toL3[cl3],r-toL3[cl3],size3[cl3])]=x;
    117         }
    118         else
    119         {
    120             tag3[bias3[cl3-1]+get(l-toL3[cl3],size3[cl3]-1,size3[cl3])]=x;
    121             tag3[bias3[cr3-1]+get(0,r-toL3[cr3],size3[cr3])]=x;
    122             if(cl3+1<=cr3-1)
    123             {
    124                 tag2[bias2[cl2-1]+get(cl3+1-bel3[toL2[cl2]],cr3-1-bel3[toL2[cl2]],tot3[cl2])]=x;
    125             }
    126         }
    127     }
    128     else
    129     {
    130         int cl3=bel3[l],cr3=bel3[r];
    131         suf2[l]=x;
    132         pre2[r]=x;
    133         ++cl2,--cr2;
    134         if(cl2>cr2)
    135             return;
    136         int cl5=bel5[cl2],cr5=bel5[cr2];
    137         if(cl5==cr5)
    138         {
    139             tag5[bias5[cl5-1]+get(cl2-toL5[cl5],cr2-toL5[cl5],size5[cl5])]=x;
    140         }
    141         else
    142         {
    143             suf4[cl2]=x;
    144             pre4[cr2]=x;
    145             if(cl5+1<=cr5-1)
    146             {
    147                 tag4[get(cl5,cr5-2,bel5[tot2])]=x;
    148             }
    149         }
    150     }
    151 }
    152 mt19937 rd(233);
    153 const int limit=1000;
    154 inline int R(int l,int r)
    155 {
    156     return rd()%(r-l+1)+l;
    157 }
    158 int main()
    159 {
    160     freopen("a.out","w",stdout);
    161     ios::sync_with_stdio(false);
    162     int T;
    163     cin>>n;
    164     init();
    165     cin>>T;
    166     for(int i=1;i<=T;++i)
    167     {
    168         int opt;
    169         if(i%limit==0)
    170             opt=1;
    171         else
    172             opt=2;
    173         if(opt==1)
    174         {
    175             int x=R(1,n);
    176             cout<<ask(x)<<'
    ';
    177         }
    178         else
    179         {
    180             int l=R(1,n),r=R(1,n),x=i;
    181             if(l>r)
    182                 swap(l,r);
    183             change(l,r,x);
    184         }
    185     }
    186     return 0;
    187 }
    View Code
  • 相关阅读:
    Solved:Spring Junit Test NoSuchMethodError
    Stack实现
    CLRS10.2-8练习
    CLRS10.2-7练习
    CLRS10.2-4练习
    CLRS10.1-7练习
    CLRS10.1-6练习
    算法:吸血鬼数字算法
    CLRS最大子数组问题
    VS快捷键
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/14514843.html
Copyright © 2020-2023  润新知