Subject to the effect
N 1 to n positive integer which is divided into m disjoint sets (not necessarily continuously set), from the m set now set minimum number of selected, for satisfying [1, n] to any one of length d is the interval have at least one digit appears in the selected set. (1 <= d <= n <= 100000, 1 <= m <= 20)
Sample Input Output
Input Sample. 1
. 3 2 2
. 1 2
2 1. 3
output samples . 1
. 1
Input Sample 2
. 5 1 1
. 5. 4. 3. 5 2 1
Output Sample 2
. 1
input samples . 3
. 7. 3. 1
. 4. 3. 1. 5 . 7
2 2. 6
. 1. 4
output sample . 3
. 3
analysis
I had wanted to do the greedy hands to play a long time not to play a sample answers and do not know how to write, and finally chose to surrender
Consider a segment of length d if eligible, it belongs to the set of numbers contained within that optionally a section, the section is valid,
The collection is being called legitimate collection interval of each segment, these collections can be composed of a set of groups (collections of collections, may be called the legitimate collection set
The minimum number of selected topics into a collection of a set of groups, this collection set to meet with all sections of the legal group has a set of intersection (the intersection of a number of elements is a set of
Not seeking direct answer demand, we in turn try
For each interval of legitimate collection set, its complement and its subsets must be illegal, the collection of these groups are removed, the rest of the group is a collection of lawful
Then enumeration can find the smallest set of groups
Specific true, descending enumerations group, the enumeration to an illegal group put its collection of subsets are marked with tags, to enumerate the legal answer is updated
Code
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,d,I,ans,ori[100005],mp[1050000],vis[25];
int main()
{
scanf("%d%d%d",&n,&m,&d);I=(1<<m)-1;ans=m;
for(int i=1,a,k;i<=m;i++){scanf("%d",&k);while(k--)scanf("%d",&a),ori[a]=i;}
for(int i=1;i<=d;i++)vis[ori[i]]++;
for(int l=1,r=d;r<=n;vis[ori[l]]--,l++,r++,vis[ori[r]]++)
{int st=0;for(int i=1;i<=m;i++)if(vis[i])st|=1<<(i-1);mp[I-st]=1;}
for(int st=I;st>=0;st--)
if(mp[st]){for(int j=1;j<=m;j++)if(st&(1<<(j-1)))mp[st^(1<<(j-1))]=1;}
else ans=min(__builtin_popcount(st),ans);
printf("%d\n",ans);
}