BZOJ3946 無聊的遊戲

2021-09-07 07:01:49 字數 2674 閱讀 7897

首先把所有串拼起來,後插入的串在前面,得到乙個大串。

那麼任意時刻,每個串是由這個大串的若干個不相交的子串從左到右拼接而成。

用線段樹維護每個串,每個節點維護乙個標記,表示區間內的串要加上什麼字首。

用可持久化線段樹維護這些串和標記,那麼合併就是線段樹的合併,因為取值區間互不相交,所以每次合併的複雜度為$o(\log l)$。

這樣就可以在$o(m\log n\log l)$的時間內支援區間加操作。

然後考慮如何計算區間lcp,設$height_i=lcp(s_i,s_)$,那麼詢問$[l,r]$就是詢問$\min(height_l,height_,...,height_)$。

用線段樹維護$height$,每當區間加的時候,對$height$的修改就是區間加上乙個定值,然後兩端點暴力重新計算lcp。

計算兩個串的lcp可以考慮維護hash值,然後二分答案,單次查詢的複雜度為$o(\log^2l)$。

時間複雜度$o(m(\log n+\log l)\log l)$。

#include#include#includeusing namespace std;

typedef unsigned int u;

const int n=50010,m=600010,maxn=131100;

int n,m,i,j,x,len,cur,st[n],en[n],q[n][3],stq[n],enq[n];u po[m];

char op[9],s[m],pool[m],str[m];

int pre[maxn],t[n],h[maxn],tag[maxn];

namespace ds

int build(int a,int b,int c,int d)

int mid=(a+b)>>1;

if(c<=mid)l[x]=build(a,mid,c,d);

if(d>mid)r[x]=build(mid+1,b,c,d);

return up(x),x;

}int merge(int x,int y,int a,int b)

inline u hash(int x,int k)

return h*po[v[x]]+f[x];}}

inline void ins(int x,int p)

inline void down(int x)

void push(int x,int a,int b,int c,int d,int p)

down(x);

int mid=(a+b)>>1;

if(c<=mid)push(x<<1,a,mid,c,d,p);

if(d>mid)push(x<<1|1,mid+1,b,c,d,p);

}void root(int x,int a,int b,int c)

down(x);

int mid=(a+b)>>1;

if(c<=mid)root(x<<1,a,mid,c);else root(x<<1|1,mid+1,b,c);

}inline int lcp(int x,int y)

return t;

}inline void tag1(int x,int p)

inline void pb(int x)

inline void up(int x)

void build(int x,int a,int b)

int mid=(a+b)>>1;

build(x<<1,a,mid),build(x<<1|1,mid+1,b);

up(x);

}void cal(int x,int a,int b,int c)

pb(x);

int mid=(a+b)>>1;

if(c<=mid)cal(x<<1,a,mid,c);else cal(x<<1|1,mid+1,b,c);

up(x);

}void change(int x,int a,int b,int c,int d,int p)

pb(x);

int mid=(a+b)>>1;

if(c<=mid)change(x<<1,a,mid,c,d,p);

if(d>mid)change(x<<1|1,mid+1,b,c,d,p);

up(x);

}int ask(int x,int a,int b,int c,int d)

inline void makepush(int l,int r,int a,int b)

inline int query(int l,int r)

int main()

for(i=1;i<=m;i++)

} for(cur=0,i=m;i;i--)if(!q[i][0])

for(i=1;i<=n;i++)

for(po[0]=i=1;i<=cur;i++)po[i]=po[i-1]*233;

for(i=1;i<=n;i++)t[i]=ds::build(1,cur,st[i],en[i]);

build(1,1,n-1);

for(i=1;i<=m;i++)if(q[i][0])printf("%d\n",query(q[i][1],q[i][2]));

else makepush(q[i][1],q[i][2],stq[i],enq[i]);

return 0;

}

bzoj3946 無聊的遊戲

並不是一道很無聊的題2333 給定n個串,支援 1.區間在最前面壓入乙個串 2.區間求lcp n 50000,sum 600000 yjc 區間壓串,先考慮區間求lcp,相鄰lcp最小值!故維護區間height最小值mh 區間壓串?對於 l 1,r mh都加上len l,r 1要hei不知道怎麼變 ...

A 無聊的遊戲

應該是博弈論 但我還沒學 這題有點水。n m a b 1 n是m的倍數 那麼這種情況下取的人贏了 2 接下來我們考慮一下走到哪部就穩操勝券了 首先你必須取 m個或者大於m並且是m的倍數,那麼我們考慮2m個特殊邊界,n 2m 舉個例子n 2.5m 我只要取到1.5m 換你取 1.5m m 你必須要取m...

JZOJ 3871 無聊的遊戲

學校的運動會開始了,體能很菜的小可可沒報任何比賽專案,於是和同學們玩乙個十分無聊的遊戲。遊戲在乙個由n n個方格組成的正方形棋盤上進行,首先在每個方格上均勻隨機地填入1到m之間的正整數 每個方格填的數均不同 然後小可可均勻隨機地選出k個1到m的數字 可能選的數不在棋盤上 把它們出現在棋盤上的方格塗黑...