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)<<'\n';
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)<<'\n';
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

 

 posted on 2021-03-10 22:51  GreenDuck  阅读(497)  评论(0编辑  收藏  举报