フェイス質問
http://darkbzoj.tk/problem/1396
問題の解決策
#include <cstdioを> する#include <iostreamの> する#include <CStringの> する#include <ベクトル> の#define RIレジスタint型 の#define N 500050 使用して 名前空間STDを、 ベクター < INT >息子[N << 1 ]。 int型のn; INTの和[N]、ANS [N]。 構造体Segment_tree { INT MINV [N << 2 ]。 無効クリア(){ 用(RI i = 1 ; iは= < 4 * N; iは++)MINV [I] = N。 } 無効プッシュダウン(int型X){ 場合(MINV [X] <MINV [X << 1 ])MINV [X << 1 ] = MINV [X]。 もし(MINV [X] <MINV [X << 1 | 1 ])MINV [X << 1 | 1 ] = MINV [X]。 } INTクエリ(int型のx、int型 LB、INT RB、INT LOC){ 場合(LB == RB)戻りMINV [X]。 プッシュダウン(X)。 INT半ば=(LB + RB)/ 2 。 もし(LOC <= MID)戻りクエリ(X << 1、LB、中間、LOC)。他の リターンクエリ(X << 1 | 1、ミッド+ 1 、RB、LOC)。 } ボイド変化(int型のx、int型 LB、INT RB、INT L、のint R、int型K){ 場合(R <LB || L> RB)のリターン; もし(L <=ポンド&& RB <= R){ MINV [X] = 分(K、MINV [X])。 返します。 } プッシュダウン(X)。 INT半ば=(LB + RB)/ 2 。 変更(X << 1、LB、中間、L、R、K)。変化(X << 1 | 1、中間+ 1 、RB、L、R、K)。 } }、T。 構造体SAM { int型 FF [N << 1 ]、LEN [N << 1 ]、CNT [N << 1 ]。 INT CH [N << 1 ] [ 26 ]。 int型の LOC [N << 1 ]。 int型ラス、TOTを。 ボイドのinit(){ ラス = TOT = 1 。 } ボイド(伸びるint型 C、INT LA){ int型の NP = ++ TOT、P =ラスと、ラス=TOT; LEN [NP] = LEN [P] + 1。CNT [NP] = 1。LOC [NP] = ラ。 一方、(!P && CH [P] [C])CH [P] [C] = NP、Pの=のFF [P]。 もし(!p)はFF [NP]は= 1 ; 他{ INT Q = CH [P]、[C]。 もし(LEN [Q] == lenの[P] + 1)FF [NP] = Q。 他の{ int型 NQ = ++ TOT; 用(RI i = 0 ; iは< 26 ; I ++)CH [NQ] [I] = CH [Q] [I]; FF [NQ] =のFF [Q]。 LEN [NQ] = LEN [P] + 1 。 FF [NP] = FFの[Q] = NQ。 一方、(P && CH [P] [C] == Q)CH [P] [C] = NQ、P = FF [P]。 } } } ボイドmaketree(){ 用(RI i = 1 ; I <= TOT; iが++ )息子[FF [I]一back(I)。 } ボイド treesum(INT X){ ため(RI i = 0 ; I <息子[X] .size(); I ++ ){ treesum(息子[X] [I])。 もし(CNT [息子[X] [I])LOC [X] = LOC [息子[X] [I]]。 CNT [X] + = CNT [息子[X] [I]]。 } } ボイドワーク(){ 用(RI I = 1 ; I <= TOT; iが++)場合(CNT [I] == 1 ){ t.change(1、1、nは、LOC [I] -len [FF [I]、LOC [I ]、LEN [FF [I] + 1 )。 和[LOC [I] -len [FF [I]] - 1 ] ++; 合計[LOC [i]が-len [I]] - 。 } } } SAM。 チャーS [N]。 INT メイン(){ sam.init()。 scanf関数(" %sの" 、S); N = STRLEN(S)。 用(RI i = 0 ; iがn <; iは++ ){ sam.extend(S [I] - ['、私は+ 1 )。 } sam.maketree()。 sam.treesum(1 )。 t.clear(); sam.work(); 用(RI i = 1 ; iが<= N iが++ ){ ANS [I] = t.query(1、1 、N、I)。 } のための(RI I = N; I> = 1 ; i-- ){ 和[I] + =和[I + 1 ]。 もし(SUM [I]> 0 ){ ANS [I] =分(ANS [i]は、ANS [I + 1 ] + 1 )。 } } のための(RI I =1 ; iが<= N; iが++)のprintf(" %d個の\ n " 、ANS [I])。 }