显然环是比较难处理的,我们不妨把环断成链,然后先忽略掉所有从n跑到1的情况.
那么很容易定义出这样的状态 表示前 个位置最后4个位置的删除状态为 (状态压缩)的最大方案数,然后每扫过一个人观测范围的终点就统计一下:
解释一下:上面状态压缩是赋予远端更大的2的次幂权重, 表示终点为 状态为 的可满足人数.
把环接上的话,我们就需要记录一下初始前4个位的状态,代码中定义 表示前 个位置 的状态为 ,最后4为为 的方案.
特别的,最后我们应该加上跨过 的人数.
#include<bits/stdc++.h>
#define lc (x<<1)
#define rc (x<<1|1)
#define gc getchar()//(p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++)
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define IT iterator
#define fi first
#define se second
#define vi vector<int>
#define SZ(a) ((int)a.size())
#define all(a) a.begin(),a.end()
using namespace std;
typedef unsigned ui;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N=1e4+10,M=5e4+10,size=1<<20,mod=998244353;
//char buf[size],*p1=buf,*p2=buf;
template<class o> void qr(o &x) {
char c=gc; x=0; int f=1;
while(!isdigit(c)){if(c=='-')f=-1; c=gc;}
while(isdigit(c)) x=x*10+c-'0',c=gc;
x*=f;
}
template<class o> void qw(o x) {
if(x/10) qw(x/10);
putchar(x%10+'0');
}
template<class o> void pr1(o x) {
if(x<0)x=-x,putchar('-');
qw(x); putchar(' ');
}
template<class o> void pr2(o x) {
if(x<0)x=-x,putchar('-');
qw(x); puts("");
}
int n,m,f[N][16][16];
struct edge{int x,y,next;}a[M]; //x表示不喜欢的集合,y表示喜欢的集合
int len,last[N];
void ins(int x,int u,int v) {
a[++len]=(edge){u,v,last[x]};
last[x]=len;
}
int calc(int x,ui y) {
int s=0;
for(int k=last[x];k;k=a[k].next) {
ui u=a[k].x,v=a[k].y;
if((y&u)||((~y)&v)) s++;
}
return s;
}
void upd(int &x,int y) {if(x<y) x=y;}
int g(int t) {
int s=0;
for(int i=1;i<=4;i++) {
int y=t>>(4-i)&31;
s+=calc(i,y);
}
return s;
}
int main() {
qr(n); qr(m);
memset(f[4],-63,sizeof f[4]);
for(int i=0;i<16;i++)
f[4][i][i]=0;
while(m--) {
int x=0,y=0,i,j,u,v;
qr(i); qr(u); qr(v);
while(u--) qr(j),x|=1<<(4-(j>=i?j-i:j-i+n));
while(v--) qr(j),y|=1<<(4-(j>=i?j-i:j-i+n));
if(i+4>n) ins(i+4-n,x,y);
else ins(i+4,x,y);
}
for(int i=5;i<=n;i++)
for(int k=0;k<16;k++) {//i前4个位置的状态
int a=calc(i,k*2),b=calc(i,k*2+1);//O(32m)
for(int j=0;j<16;j++) {//[1,4]的状态
upd(f[i][j][(k&7)*2],f[i-1][j][k]+a);
upd(f[i][j][(k&7)*2+1],f[i-1][j][k]+b);//O(256n)
}
}
int ans=0;
for(int j=0;j<16;j++)
for(int k=0;k<16;k++)
upd(ans,f[n][j][k]+g(k*16|j));
pr2(ans);
return 0;
}