--- ---復元コンテンツ始まります
v1.0を、改正のギャングを求めます
我々はすべて知っているように、Xinlongの妹は悪性腫瘍です。
データ構造が多いがん。
これは、ブロックのうちで最もです。
優れた(暴力)ショー(力)のデータ構造を学ぶためまあ、彼らは巣今日 - ブロック
ラブリー吉野。
QAQ
パート1ブロックとは何ですか?
各ブロックの複数のブロックに配列に等しい定義、、、保守情報、および組み合わせによってブロック、。
パート2ブロック原則、達成するために?
今、私たちは間隔を求めていると、シーケンス番号、区間追加ごとに、問題を抱えている(私たちがいないと仮定すると、ツリーラインと呼ばれるものです)
暴力の実践:
暴力、暴力の問い合わせを修正し、明らかにT、O(n²)の時間計算量を飛びます。
暴力を最適化する検討します。
Ωブロックにシーケンスは、各ブロックはTAGを維持します。
L、R-片部との間隔が断片化ブロックの部分に分割されています。
モノリシック部分については、我々は、タグブロックxに直接追加します。
散乱部分については、我々は暴力を追加します。
クエリは同じです。
ブロックの部分のために、ブロックは、元と+(N /ω)*タグです>
散乱部品、直接暴力お問い合わせください。
時間の複雑さ。
作品なので、O(ω)の時間複雑ωアップ。
(N /ω)の時間複雑度はO(n /ω)までによって断片化。
明らかω= SQRT(n)が最適です。
したがって、ブロックのM *のSQRT(N)の時間複雑。
ブロックは、おそらく実現します:
ブロックに属する点を表すベルレコードアレイ。
LFT、RGTアレイを記録する、各ブロックの代表点は、左と右の点
そして、情報と統計の各部分。
各クエリのために
同じブロック、暴力の照会で2つのエンドポイントの場合。
それ以外の場合は、情報のクエリの最初の部分は、散乱暴力問合せ部
各変更のため。
情報タグの直接のヒットシングル曲は、暴力断片化されたパーツを変更します。
たとえば、三の部分は、(原因異なる時間にタイトルが全く異なる、コードスタイルかもしれ書い変更になる場合があります)
1. Danfeiヒツジ(luogu3203)
タイトル効果:Lostmonkey羊は、i番目のユニットに到達したとき、それは、次のステップKIを再生KI + I番目のデバイスに到達し、各デバイスが初期弾性係数kiを設定し、n個のデバイスのラインに沿って地面に置きます、iは装置、羊DanfeiのKIの存在を+た場合。羊は、いくつかのシェルがDanfeiます後、それは、i番目のユニットから開始されたときに知ってほしいです。
遮断手段の基本的な問題は、記録時間のそれぞれは、現在のポイント位置のブロックから飛び出すノードの少数後にジャンプすることができます。
代码:
#include <iostream>
#include <stdio.h> #include <string> #include <math.h> using namespace std; const int maxn=200005,maxm=505; int n,m,Q,num[maxn],bel[maxn],sum[maxn],outt[maxn]; struct block { int l,r; } a[maxn]; inline int read() { int x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar(); return x; } void doit(int l,int r) { for (int i=r; i>=l; i--) if (i+num[i]>a[bel[i]].r) sum[i]=1,outt[i]=i+num[i]; else sum[i]=sum[i+num[i]]+1,outt[i]=outt[i+num[i]]; } int main() { n=read(); m=sqrt(n); if (m*m<n) m++; int s=0; for (int i=1; i<=n; i++) num[i]=read(); for (int i=1; i<=n; i+=m) a[++s].l=i,a[s].r=i+m-1; if (s<m) a[++s].l=s*m+1,a[s].r=n; s=1; for (int i=1; i<=n; i++) { if (i>a[s].r) s++; bel[i]=s; } doit(1,n); Q=read(); while (Q--) { int x=read(),y=read()+1; if (x==1) { int ans=sum[y],x=outt[y]; for (int i=bel[y]; i<=m&&x<=n; i++) ans+=sum[x],x=outt[x]; printf("%d\n",ans); } else { int z=read(); num[y]=z; doit(a[bel[y]].l,a[bel[y]].r); } } return 0; }
2.lucky array(CF121E)
其实这题更简单,本该放在前面。
题目大意:区间加法,区间幸运数个数。
因为值域很小,我们发现在值域中的幸运数个数为30,所以我们先打个表,然后分块。
先统计每一个块内每一个数的出现次数,然后对于加法,我们还是打TAG,只不过在查询的时候要查询=(幸运数字-TAG)的个数
然后就好了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define Rint register int #define Temp template<typename T> #define update(x,y,z) num[x][y]--,num[x][y+=z]++ using namespace std; Temp inline void read(T &x) { x=0;T w=1,ch=getchar(); while(!isdigit(ch)&&ch!='-') ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); x*=w; } const int t[30]={4,7,44,47,74,77,444,447,474,477,744,747,774,777,4444,4447,4474,4477 ,4744,4747,4774,4777,7444,7447,7474,7477,7744,7747,7774,7777}; const int m=317*5; const int maxn=1e5+10; int n,q,cnt; int a[maxn]; int num[105][maxn],id[maxn],low[maxn],high[maxn],add[maxn]; int vis[10010]; int main() { read(n);read(q); for (int i=1;i<=n;++i) { read(a[i]); id[i]=i/m+1; num[id[i]][a[i]]++; } cnt=id[n]; for (int i=1;i<=cnt;++i) { low[i]=(i-1)*m; high[i]=i*m-1; } low[1]=1;high[cnt]=n; for (int i=0;i<30;++i) vis[t[i]]=1; while(q--) { char kind[10]; int l,r,d; scanf("%s%d%d",kind,&l,&r); int lx=id[l],rx=id[r]; if(*kind=='a') { scanf("%d",&d); if(lx==rx) { for (int i=l;i<=r;++i) update(lx,a[i],d); } else { for (int i=l;i<=high[lx];++i) update(lx,a[i],d); for (int i=lx+1;i<rx;++i) add[i]+=d; for (int i=low[rx];i<=r;++i) update(rx,a[i],d); } } else { int ans=0; if(lx==rx) { for (int i=l;i<=r;++i) ans+=vis[a[i]+add[lx]]; } else { for (int i=l;i<=high[lx];++i) ans+=vis[a[i]+add[lx]]; for (int i=lx+1;i<rx;++i) { for (int j=0;j<30;++j) if(add[i]<=t[j]) ans+=num[i][t[j]-add[i]]; } for (int i=low[rx];i<=r;++i) ans+=vis[a[i]+add[rx]]; } printf("%d\n",ans); } } return 0; }
part four-Ynoi(不提供代码,不然没啥意思)
1.luogu5397 天降之物(第四分块)
题目大意:将所有x变成y,求最小的|i-j|使得a[i]==x && a[j]==y。
定义size[x]为x出现次数.
by lxl(写了一遍题解发现自己写得太垃圾了)
2. 五彩斑斓的世界。(第二分块)
题目大意:把区间>x的数减去x,求区间l,r内x的出现次数,值域1e5
解法:
提示了值域1e5,时间复杂度肯定与值域有关。
这题明显有一个性质,就是所有数的最大值总是单调不增的。
考虑利用这个性质
然后,他是要把l,r内>x的数-x,可一转化为把所有数-x,然后把<0的数+x
当最大值>=x*2时,把(1,x)合并到(x+1,x*2)
否则把(x+1,v)合并到(1,v-x)
这个用并查集维护即可。
所以神仙多多指教啊
---恢复内容结束---