https://www.luogu.org/problemnew/show/P3732node
Anihc國提升社會生產力水平.落實好以人民爲中心的發展思想。決定進行供給側結構性改革。ios
爲了提升供給品質.你調查了某個產業近來n個時期的供求關係平衡狀況.每一個時期的狀況都用0或1中的一個數字來表示.因而這就是—個長度爲n的01字符串S。爲了更好的瞭解這一些數據.你須要解決一些詢問.咱們令data(l,r)表示:在字符串S中.起始位置在[l,r]之間的這些後綴之中,具備最長公共前綴的兩個後綴的最長公共前綴的長度。git
對於每個詢問L,R.求sigma(data(i,R))。數組
因爲你其實根本沒有時間調查,因此這些數據都是亂編的,即串S中的每一位都是在0和1之間隨機產生的。spa
參考:https://msy.blog.luogu.org/solution-p3732
code
最後一句話很皮,因而咱們思考下發現公共前綴必定很短,連(看)猜(題)帶(解)蒙大概是40吧。blog
因而咱們把詢問離線,按照$r$排序,從左到右掃一遍$i$,將以$i$爲首的40位字符加入到trie樹中,以此維護$pos[k]$表示最小的區間$[pos[k],i]$,使得$data(pos[k],i)=k$。排序
(仍是很好維護的,若是不知道怎麼維護能夠看參考也能夠直接看代碼。)字符串
爲何咱們構造了$pos$數組呢?實際上是由於$data$的單調不增性。get
由此咱們發現$data(pos[k+1]+1,i)$到$data(pos[k],i)$都是$k$。
答案就呼之欲出了。
#include<queue> #include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1e5+5; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int a[2],ed; }tr[N*40]; struct data{ int l,r,id; }d[N]; char s[N]; int n,q,tot,pos[50]; ll ans[N]; inline bool cmp(data a,data b){ return a.r<b.r; } void insert(int st){ int now=0; for(int i=st;i<=min(n,st+39);i++){ int w=s[i]-'0'; if(!tr[now].a[w])tr[now].a[w]=++tot; now=tr[now].a[w]; if(tr[now].ed) pos[i-st+1]=max(pos[i-st+1],tr[now].ed-i+st); tr[now].ed=i; } } int main(){ n=read(),q=read(); scanf("%s",s+1); for(int i=1;i<=q;i++){ d[i].l=read(),d[i].r=read(); d[i].id=i; } sort(d+1,d+q+1,cmp); for(int i=1,j=1;i<=n;i++){ insert(i); while(j<=q&&d[j].r==i){ for(int k=1;k<=40;k++){ if(pos[k]>=d[j].l){ ans[d[j].id]+=(ll)k*(pos[k]-max(pos[k+1],d[j].l-1)); }else break; } j++; } } for(int i=1;i<=q;i++)printf("%lld\n",ans[i]); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文做者:luyouqi233。 +
+歡迎訪問個人博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++