【Codeforces】CF367D Sereja and Sets

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);
}

 

Guess you like

Origin www.cnblogs.com/firecrazy/p/11753909.html