n(n<=1e5)个区间,第i个区间[li,ri](1<=li<=ri<=m,1<=m<=1e9),
保证区间内的每个端点不会被覆盖超过8次,选一些区间使得被覆盖的次数为奇数的点最多
输出最大的被覆盖的次数为奇数的点的个数
https://codeforces.com/contest/1313/submission/71864317
https://www.bilibili.com/video/BV1Q7411M7S9?p=5
首先离散化,压成2e5个左开右闭的区间,每个新区间单独考虑,
dp[i][S]表示第i个新区间,8个线段覆盖其的状态为S时,只考虑<=i的新区间时的最大点数
当前x区间选的线段可能和x-1区间选的线段有公有的部分,
如果有一些线段同时覆盖了x-1和x的话,就要么都取,要么都不取
那dp[i][S]表示到第i个区间,第i个区间覆盖状态是S的时候,
如果S包含的x和x-1的公有状态是T,dp[i][S]只能从dp[i-1][T的超集]转移而来,
先把T的超集的答案缩到T更新T,再把S缩到T,用T更新S,思路大致如此
但是用tmp数组做跳板的时候,二者下标不一致,即公有状态T在seg[i-1]的下标是j,在seg[i]的下标是k,
这里就新开两个vector,使其pre[l]为seg[i-1]中的j,now[l]为seg[i]中的k,
这样T的超集中出现了第j位的时候,对tmp的第l位赋值,
S出现了第k位的时候,就从tmp含l的位进行转移,这样下标就一致了
至于考虑x的时候,为什么不用考虑x-2及更小的区间与x的一致性,
是x-1这个区间已经和前面一致了,所以x和x-1保持一致就可以了,
类似扫描线,不可能断的
#include
using namespace std;
#define pb push_back
const int N=1e5+10,M=2e5+10,S=1<<8;
int n,m,k,l,r,x[M],c;
int dp[M][S],tmp[S],bit[S],ans;
vectorseg[M];
struct line{
int l,r;
}e[N];
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i>1]+(i&1))%2;
}
for(int i=1;i<=n;++i){
scanf("%d%d",&l,&r);
r++;
e[i]={l,r};
x[++c]=l;x[++c]=r;
}
sort(x+1,x+c+1);
c=unique(x+1,x+c+1)-(x+1);
for(int i=1;i<=n;++i){
e[i].l=lower_bound(x+1,x+c+1,e[i].l)-x;
e[i].r=lower_bound(x+1,x+c+1,e[i].r)-x;
for(int k=e[i].l;kpre,now;
for(int j=0;j>pre[k]&1){
st|=(1<>now[k]&1){
st|=(1<