1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 int bit[1<<9]; 5 set<int>s; 6 pair<int,int>a[200007]; 7 int pre[10]; 8 int dp[1<<9]; 9 int pos[200007]; 10 int main(){ 11 ios::sync_with_stdio(false); 12 cin.tie(NULL); 13 cout.tie(NULL); 14 int n,m,k; 15 cin>>n>>m>>k; 16 for(int i=1;i<=n;++i){ 17 int x,y; 18 cin>>x>>y; 19 a[2*i-1]={x,i};//记录线段端点位置 20 a[2*i]={y+1,-i};//前缀相减,故存右端点时+1 21 } 22 for(int i=0;i<=k;++i) 23 pre[i]=1<<i;//二进制下第i位为1的数字大小 24 for(int i=1;i<pre[k];++i){ 25 bit[i]=bit[i>>1]^(i&1);//把i在二进制下为1的个数为奇数的bit[i]变为1 26 dp[i]=-1e9; 27 } 28 sort(a+1,a+1+2*n); 29 int last=0;//前一个端点位置 30 for(int i=0;i<k;++i) 31 s.insert(i);//每条线段给一个编号 32 for(int i=1;i<=2*n;++i){ 33 int now=a[i].first; 34 int temp=a[i].second; 35 for(int j=1;j<pre[k];++j) 36 dp[j]+=bit[j]*(now-last);//当前情况下线段数为奇数的可以加上这一段线段的长度 37 last=now;//这个端点用过了,记下他的位置 38 if(temp>0){//这个端点是左端点 39 pos[temp]=*s.begin();//去集合里领取一条线段的编号,记作当前线段的编号 40 s.erase(pos[temp]); 41 for(int j=0;j<pre[k];++j)//枚举所有情况 42 if(j&pre[pos[temp]])//包含这条线段的情况 43 dp[j]=max(dp[j],dp[j^pre[pos[temp]]]);//更新最大值 44 } 45 else{//这个端点是右端点 46 temp=-temp; 47 s.insert(pos[temp]);//这条线段用完了还给集合 48 for(int j=0;j<pre[k];++j)//枚举所有情况 49 if(j&pre[pos[temp]]){//包含这条线段的情况 50 dp[j^pre[pos[temp]]]=max(dp[j^pre[pos[temp]]],dp[j]);//更新最大值 51 dp[j]=-1e9;//这条线段不取,包含这条线段的情况初始化 52 } 53 } 54 } 55 cout<<dp[0];//所有线段都遍历一遍以后,所有线段都不取,dp[0]为扫过一遍的答案 56 return 0; 57 }