Codeforces 750EセグメントツリーDP

質問の意味:1:あなたの文字列を与えるために、2がある場所の文字を変更します。2:配列2017、及び2016ない配列を含むサブストリングを作成、削除する文字の最小数のサブストリングrに問い合わせLは、?

思考:ツリーセグメントDPを、我々は、1を0の状態を設定し、2、3、4は、次のとおりと組み合わさヌル、2、20、最小コスト201、2017年、我々は、状態遷移行列を取るために断面寸法セグメントツリーを使用し、二つの隣接するサブストリングに直接転送。

コード:

#include <ビット/ STDC ++ H> 
に#define INF 0x3f3f3f3f 
の#define LS(<< 1 O)
の#define RS(O << 1 | 1)
使用して名前空間std。
const int型MAXN = 200010; 
[MAXN] int型。
チャーS [MAXN]。
構造体ノード{ 
	int型のF [5] [5]。
	INITを無効(INT X){ 
		(INT i = 0; iは<5; I ++)のために{ 
			ため(int型J = 0; J <5; J ++){ 
				(I == j)が続けば、
				F [i] [j]はINFを=。
			} 
		} 
		もし(x == 2){ 
			F [0] [0] = 1、F [0] [1] = 0; 
		}そうであれば(x == 0){ 
			F [1] [1] = 1、F [1] [2] = 0;			
		}そうであれば(x == 1){ 
			F [2] [2] = 1、F [2] [3] = 0; 
		}もしそうでなければ(X == 7){  
			F [3] [3] = 1、F [3] [4] = 0;
		}もしそうでなければ(X == 6){ 
			F [3] [3] = 1。
			F [4] [4] = 1。
		他の場合}(X == -1){ 
			ため(; iは5 <; I = 0 int型私は++)
				F [i]は[I] = INF。
		}他{ 
			ため(; iは5 <; I = 0 int型私は++)
				F [i]は[I] = 0; 
		} 
	} 
	
	ボイドプリント(){ 
		(I = 0 int型、iが5 <; I ++の)のために{ 
			ため(INT J = 0; J <5; J ++){ 
				IF(F [I] [J] == INF)のprintf( "INF"); 
				他のprintf( "%dの"、F [i]は[J])。
			} 
			のprintf( "の\ n"); 
		} 
	} 
}。
ノードTR [MAXN * 4]。
ノードマージ(ノードT1、ノードT2){ 
	ノードANS。
	ans.init(-1)。
// ans.init(-1); 
// printfの( "ANSの\ nを");
// ans.print(); 
}
// printfの( "T1の\ nを");
// t1.print(); 
// printfの( "T2の\ nを"); 
// t2.print(); 
	以下のために(; iは5 <; I = 0 int型私は++){ 
		ため(int型J = I; J <5; J ++){ 
			ための(int型K = I; K <= J; ++ K){ 
				ans.f [I] [ J] =分(ans.f [I]、[J]、t1.f [I] [K] + t2.f [K] [J])。
			} 
		} 
	} 
//のprintf( "ANSする\ n"); 
// ans.print(); 
	ANSを返します。
} 
ボイドビルド(int型、L、O INT、INT R){ 
	(L == R)なら、{ 
		TR [O] .INIT([L])。
		返します。
	} 
	INT半ば=(L + R)>> 1。
	(LS、L、ミッド)を構築。
	(RS、ミッド+ 1、r)を構築します。
	TR [O] =マージ(TR [LS]、TR [RS])。 
	{(L == R)場合
ボイド更新(int型、L、O INT、INT R、INT QL、QR INT、INTヴァル){
	それ以外(QR>中旬)ANS =クエリ(RS、ミッド+ 1、Rであれば、
		TR [O] .INIT(ヴァル)。
		返します。
	} 
	INT半ば=(L + R)>> 1。
	IF(QL <= MID)更新(LS、L、中間、QL、QR、ヴァル)。
	(QR> MID)更新(RS、ミッド+ 1、R、QL、QR、val)であれば、
	TR [O] =マージ(TR [LS]、TR [RS])。
} 
ノードクエリー(INT 0、int型のL、R INT、INT QL、QR INT){ 
	IF(L> = QL && R <= QR){ 
		戻りTR [O]。
	} 
	INT半ば=(L + R)>> 1。
	ノードANS; 
	ans.init(-1)。
	IF(QL <=ミッド&& QR> MID)ANS =(クエリ(LS、L、中間、QL、QR)、クエリ(RS、ミッド+ 1、R、QL、QR))マージ。
	他のANS =クエリ(LS、L、ミッド、QL、QR)(QL <= MID)の場合。
	ANSを返します。
} 
int型のmain(){ 
	int型N、M、L、R。
	scanf関数( "%d個の%d個"、
	scanf関数( "%sの"、S + 1)。
	以下のために(INT i = 1; iが<= N; iは++){ 
		[I] = sの[I] - '0'。
	} 
	(1、1、n)を構築します。
	{(; I <= M I ++はiは1 = INT)のため
		のscanf( "%dの%のD"、&L&R)。
		ノードANS =クエリ(1、1、N、L、R)。
		IF(ans.f [0] [4] == INF)のprintf( " - 1つの\ n"); 
		他のprintf( "%Dを\ n"、ans.f [0] [4])。
	} 
}

  

おすすめ

転載: www.cnblogs.com/pkgunboat/p/11488340.html