八省聯考2018 制胡竄

2022-09-02 09:24:10 字數 2436 閱讀 1348

首先,本題parent tree上樹上倍增+線段樹合併找出每個點的 \(\text\) 集合應該是沒得說的。

於是我們現在考慮知道了 \(\text\) 集合以及詢問串長度 \(len\) 怎麼求出答案。

首先,乙個正常人稍微想想,都應該得出正難則反的推論,因為無論怎麼說不合法的劃分明顯要來得比較工整。

於是問題轉化為割兩刀,能否切斷所有串。我們設最左端串的右端點為 \(l\),最右端串的右端點為 \(r\)。同時,設所有串的端點集合為 \(p_1,p_2,\dots,p_m\)。明顯有 \(p_1=l,p_m=r\)。

若出現三個及以上無交串則無不合法劃分。這是顯然的,因為一次只能割斷乙個無交串。

若最左端的串與最右端的串有交,則兩兩串皆有交。考慮此種情形。

首先,此時,所有串的交集非空,等於最左串與最右串的交集,這是顯然的。

則,若有至少一刀砍到了此交集上,則所有串就都被砍到了。

交集長度為 \(l-r+len\)。從中砍兩刀,總方案數為 \(\dbinom\)。從中只砍一刀,方案數為 \((l-r+len-1)\times(n-len)\)。

若一刀都沒有砍到此交集上,則顯然有一刀砍到了 \(p_\) 的交集上,另一刀砍到了 \(p_\) 的交集上,其中 \(i\in[1,m)\)。

若最左端串與最右端串無交。

首先,對於與左右兩端串皆有交的串來說,其仍然可以與前一種情形一樣地計算。準確來說,若設 \(lp\) 表示最左的與 \(r\) 有交的串,\(rp\) 表示最右的與 \(l\) 有交的串,則仍有此部分答案為 \(\big(\sum\limits_^p_(p_-p_i)\big)-(r-len+1)(p_-p_)\)。

但是,有乙個例外。我們可以在 \([p_-len+1,l]\) 這段區間裡砍一刀。這時,找到 \(np\) 是最左的與 \(l\) 無交的串,則此串必與 \(r\) 有交。於是,另一刀就砍在 \(np\) 與 \(r\) 的交集上,這時也能達成目標。

時間複雜度 \(o(n\log n)\)。

**:

#includeusing namespace std;

typedef long long ll;

int read()

int n=read(),m=read(),cnt=1,anc[200100][20],id[100100],tot;

char s[100100];

struct suffix_automatont[200100];

int add(int x,int c)

int y=t[x].ch[c];

if(t[y].len==t[x].len+1)

int yy=++cnt;t[yy]=t[y],t[yy].len=t[x].len+1;

t[xx].fa=t[y].fa=yy;

for(;x&&t[x].ch[c]==y;x=t[x].fa)t[x].ch[c]=yy;

return xx;

}int rt[200100];

#define mid ((l+r)>>1)

struct section

section(int p)

section(int l,int r,ll v)

void print()const

bool empty()const

friend section operator+(const section&l,const section&r)

};struct segtreeseg[4001000];

void modify(int &x,int l,int r,int p)

int doubling(int l,int r)

section queryarea(int x,int l,int r,int l,int r)

int lp=outeraskright(rt[x],1,n,l,r-len+1),rp=outeraskright(rt[x],1,n,l,l+len-1),np=outeraskleft(rt[x],1,n,l+len-1,r);

// printf("%d %d %d\n",lp,rp,np);

ll ret=0;if(lp<=rp)ret+=queryarea(rt[x],1,n,lp,rp).val-1ll*(r-len+1)*(rp-lp);

if(np>r-len+1)ret+=1ll*(l-rp+len-1)*(np-r+len-1);

return ret;

}int main()

// for(int i=1;i<=cnt;i++)printf("%d ",t[i].len);puts("");

for(int i=1,l,r;i<=m;i++)l=read(),r=read(),printf("%lld\n",1ll*(n-1)*(n-2)/2-calc(doubling(l,r),r-l+1));

return 0;

}

九省聯考 2018 制胡竄

對於乙個字串 s 我們定義 s 表示 s 的長度。接著,我們定義 s i 表示 s 中第 i 個字元,s 表示由 s 中從左往右數,第 l 個字元到第 r 個字元依次連線形成的字串。特別的,如果 l r 或者 l 1,s 或者 r 1,s 我們可以認為 s 為空串。給定乙個長度為 n 的僅由數字構成...

制胡竄考前總結

利用了回文串的對稱性質,o n 的時間複雜度就可以求出以每個點作為回文中心時最長回文串的長度 個人習慣 mc 的值為回文串長度,而不是回文串長度 1 int n,mc maxn 1 n char s maxn d maxn 1 inline void manacher 常見用法是先求出 mc 然後根...

八省聯考2018 劈配

題目這題目,乍一眼看上去像乙個dp,因為這個資料範圍一般都是dp,但是考慮到轉移有後效性,所以顯然是做不了dp的。考試的時候像著怎麼設狀態沒有後效性,失敗了,就只打了乙個70分的暴力,還掛了20分。這題其實是個 網路流 匹配 真心看不出,然後我寫部落格的時候旁邊yl神犇看見了,嘲諷了我一波,我是真的...