好題啊
\(sa+st\text+\text\)
我們先強行把所有的串連起來,串與串之間插入特殊字元,姓和名之間也插入特殊字元
之後跑一遍\(sa\),求出\(sa\)和\(het\)
對於所有的詢問串,我們標記好他們的開頭,之後我們對於排好序的字尾建乙個\(st\)表,找到每個詢問串往左往右最多可以擴充套件到**
擴充套件到**自然是這個區間內的\(het\)的最小值大於等於詢問串的長度了,這個二分+\(st\)表就能做到
第一問就變成了區間數顏色了,這個套上乙個莫隊就可以了
第二問是求出一種顏色被數了多少次,我們在莫隊的時候順便打上乙個時間戳,如果在乙個詢問裡這個顏色第一次出現我們就標記好這個詢問的時間,等到下一次這個顏色被完全刪除的時候我們利用這個操作的時間做乙個差就好了
**
#include#include#include#include#include#define maxn 500005
#define re register
#define ll long long
#define lowbit(x) ((x)&(-x))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
int tax[maxn],rk[maxn],sa[maxn],het[maxn],tp[maxn],f[maxn],s[maxn];
int to[maxn],c[maxn],st[maxn][19],logg[maxn],ans[maxn],li[maxn],cnt[maxn];
int n,m,l,m,len,sz,ans;
inline void qsort()
struct ask a[maxn];
inline void add(int x,int o)
inline void del(int x,int o)
inline int query(int l,int r)
int k=0;
for(re int i=1;i<=l;i++)
memset(st,20,sizeof(st));
for(re int i=1;i<=l;i++) st[i][0]=het[i];
for(re int i=2;i<=l;i++) logg[i]=1+logg[i>>1];
for(re int j=1;j<=18;j++)
for(re int i=1;i+(1<>1;if(query(mid,j)>=li[i]) a[i].x=mid-1,r=mid-1;else l=mid+1;}
if(!a[i].x) a[i].x=j;
l=j+1,r=l;
while(l<=r)
if(!a[i].y) a[i].y=j;
} sz=std::sqrt(l);
std::sort(a+1,a+m+1,cmp);
int l=0,r=0;
for(re int i=1;i<=m;i++)
for(re int i=1;i<=m;i++) printf("%d\n",ans[i]);
for(re int i=1;i<=n;i++) printf("%d ",c[i]);
return 0;
}
SCOI2012 喵星球上的點名
有n個串,代表n個人的姓氏和名字,都是用很多個數字表示的,比如我姓1,2,3,4,名4,5,6,7。然後有m個點名串,如果點到了某個人的姓或名裡面的某一串,那個人就被點到,不過乙個人在乙個點名串中只能被點一次。比如點名串是2,3,4,我的姓中含有2,3,4,那麼我就會被叫到。求每個學生分別被叫到多少...
SCOI2012 喵星球上的點名
給出n個模式串,m個文字串,每個模式串由兩部分組成,我們認為乙個模式串被乙個文字串包含只要這個文字串包含它的兩部分中的其中一部分的子串。求每個文字串包含多少個模式串,每個模式串又被多少個文字串包含。1 n 20000,1 m 50000,模式串總長和文字串的總長分別不超過100000 保證模式串和文...
SCOI2012 喵星球上的點名
對於第乙個詢問,對於姓名串建廣義字尾自動機,那麼我們對於插入乙隻喵的姓名串,要將這兩個 姓和名 串的所有字串位置打標記,怎麼搞呢,其實可以直接插入暴力向上跳,複雜度的話 對於乙個串假設長度為x,那麼插入複雜度是min x x,x n 而最多只有n x個這樣的串,算一下總的複雜度上界是n根號的。然後就...