効果の対象に
今の最小数を設定し、M個のセットから(必ずしも連続的に設定されていない)、m個の互いに素なセットに分割されているnは正の整数をN 1、長さのいずれかに[1、n]を満足するため、選択されましたDは間隔が少なくとも一つの数字が選択されたセットに表示されています。(1 <= D <= N <= 100000、1 <= M <= 20)
サンプル入力出力
入力サンプル。1
。3 2 2
1つの2
2 1 3
出力サンプル 1
。1
入力サンプル 2
。5 1
。5 4 3 5 2 1
出力サンプル 2
。1つの
入力サンプル。3
。7 3. 1
。4. 3. 1. 5 7
2 2 6
。1. 4
出力サンプル。3
。3
分析
私は、サンプルの回答を再生しないように長い時間を再生するために貪欲な手をやってみたかったと書き込みをする方法がわからない、そして最終的に降伏することを選びました
対象、それは必要に応じて内のセクションを含んでいた数字の組に属している場合、セクションが有効である、長さdのセグメントを検討
コレクションは、コレクションのコレクション(これらのコレクションは、グループの集合で構成することができ、各セグメントの正当収集間隔と呼ばれている、正規コレクションセットと呼ばれることもあります
グループのセットのコレクションに選択したトピックの最小数、法的グループのすべてのセクションで満たすように設定されたこのコレクションは、交差点の集合(要素数の交点がセットであるました
直接の回答需要を求めていない、私たちは順番にしてみてください
正当コレクションセットの各区間について、その相補体およびそのサブセットは違法である必要があり、これらの基のコレクションが削除され、グループの残りの部分は合法の集合であります
次に列挙は、グループの最小セットを見つけることができます
サブセットの具体的な真の、列挙型グループを降順、違法なグループへの列挙が置かそのコレクションが更新され、法的な答えを列挙するために、タグが付いています
コード
書式#include <cstdioを>
する#include <アルゴリズム>
使用して 名前空間はstdを、
INTの N、M、D、I、ANS、ORI [ 100005 ]、MP [ 105万 ]、VIS [ 25 ]。
INT メイン()
{
scanf関数(" %D%D%D "、&N、&M、&D)、I =(1 << M) - 1 ; ANS = M。
用(int型 I = 1、、K、I <= M; iは++){scanf関数(" %のD "、&K); 一方、(K - )のscanf(" %dの"、&A)、ORI [A] = I。
int型 I = 1 iが= D <; I ++)はVIS [ORI [I]] ++ ;
用(int型、L = 1、R = D; R <= N; VIS [ORI [L]は] - 、L ++、R ++、VIS [ORI [R]] ++ )
{ int型 ST = 0。以下のために(int型 I = 1 ; I <= M; iは++)場合(VIS [i])とST | = 1 <<(I- 1); MP [I-ST] = 1 ;}
のための(int型 ST = I。 ST> = 0 st--; )
場合(MP [ST]){ ため(INT J = 1 ; J <= Mであり、j ++)場合(ST&(1 <<(J- 1)))MP [ST ^(1 <<(J- 1))] = 1 ;}
そう ANS = 分(__ builtin_popcount(ST)、ANS)。
printf(" %d個の\ n " 、ANS)。
}