BZOJ4516 生成魔咒,字尾陣列 Splay

2021-07-12 03:52:01 字數 1326 閱讀 5554

time:2016.05.28

author:xiaoyimi

思路:

(考場上寫的60分kmp……)

學過字尾陣列的都知道,乙個串裡不同子串的個數=∑(

n−sa

[i]−

heig

ht[i

])對於問題中串每次插入乙個數字,它實際上使長度增加了1,即∑n

=n2=

(n+1

)2,對答案的貢獻是2n+1,注意這裡的n不是總長,而是插入前的串的長度,而∑s

a[i]

=n(n

−1) ,對答案的貢獻是-n,所以每次增加的就是n+1,同時插入的數字會對相鄰的height產生影響,並會產生新的兩個height,查詢排名這個東西可以用splay解決,求任意兩個子串(實際上這裡是字尾)的lcp直接預處理st表就可以了

注意:

開long long,且處理後的串是倒轉的,注意下標

**:

#include#define m 100003

#define ll long long

using namespace std;

int n,root;

int w[m],sa[m],rank[m],tmp[m],cnt[m],id[m],height[m],f[m][18];

ll ans;

struct splaya[m];

struct discb[m];

bool cmp(disc x,disc y)

void sa(int

len,int up)

}void height(int

len)

}int lcp(int a,int b)

void made(int id,int x)

void rorate(int x,bool mk)

a[x].fa=a[y].fa;

a[y].fa=x;

a[x].ch[mk]=y;

ct(y);ct(x);

}void splay(int x,int goal)

else

if (a[a[y].fa].ch[0]==y)

else

}if(!goal) root=x;

}void insert(int id,int x)

intnow=root,f=1;

while (f)

splay(id,0);

}int find_next_max(int x)

int find_next_min(int x)

main()

}

BZOJ 4516 生成魔咒

串串長度 n 1 05 n leq 10 5 n 10 5,串中元素x 1 09 x leq 10 9 x 10 9,問每加入乙個數後本質不同的子串數 裸的s am samsa m或者是離線sasa sa。這裡討論sasa sa做法。實際上問題就是把整個串翻轉一下 然後就相當於計算完每個串的貢獻以後...

bzoj4516 SDOI2016 生成魔咒

time limit 10 sec memory limit 128 mb submit 376 solved 232 submit status discuss 魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1 2 拼湊起來形成乙個魔咒串 1,2 乙個魔咒串 s 的非空字串...

bzoj4516 Sdoi2016 生成魔咒

4516 sdoi2016 生成魔咒 time limit 10 sec memory limit 128 mb submit 575 solved 327 submit status discuss 魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1 2 拼湊起來形成乙個魔咒...