题目链接:传送门
题目思路:
将m个区间按中点排序,
设第一个"题解"的中点为x,第二个"题解"的中点为y ,显然,对于每一个区间 的中点 mid ,x与y 谁更接近mid谁相交的长度就越长。显然,对于mid单调不减的序列,必定是前一部分与第一个相交更优,后一部分与第二个题解交更优,而这两个部分的分界点就是 z = (x+y)/2 ;
若mid > z ,则区间与第二个题解相交更优,而后面的 mid’ >= mid , 所以后面也都和第二个题解相交更优,因此分成了两部分。
接下来,直接按照上述思路写即可。
pre[i] 表示 中点<=i 的区间序号(排序后);
w[i][j] 表示 [i , i + k -1] 与前 j 个区间相交长度的的前缀和。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 typedef unsigned long long uLL; 5 typedef pair<int,int> pii; 6 typedef pair<LL,LL> pLL; 7 typedef pair<double,double> pdd; 8 const int N=2e3+5; 9 const int M=1e7+5; 10 const int inf=0x3f3f3f3f; 11 const LL mod=998244353; 12 const double eps=1e-8; 13 const long double pi=acos(-1.0L); 14 #define ls (i<<1) 15 #define rs (i<<1|1) 16 #define fi first 17 #define se second 18 #define pb push_back 19 #define eb emplace_back 20 #define mk make_pair 21 #define mem(a,b) memset(a,b,sizeof(a)) 22 LL read() 23 { 24 LL x=0,t=1; 25 char ch; 26 while(!isdigit(ch=getchar())) if(ch=='-') t=-1; 27 while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } 28 return x*t; 29 } 30 struct node{ int l,r; }a[N]; 31 int w[N][N],pre[N]; 32 bool cmp(node p,node q) 33 { 34 return p.l+p.r<q.l+q.r; 35 } 36 int main() 37 { 38 int n=read(),m=read(),k=read(); 39 for(int i=1;i<=m;i++) a[i].l=read(),a[i].r=read(); 40 sort(a+1,a+m+1,cmp); 41 for(int i=1;i+k-1<=n;i++) 42 { 43 int l=i,r=i+k-1; 44 for(int j=1;j<=m;j++) 45 w[i][j]=w[i][j-1]+max(0,min(r,a[j].r)-max(l,a[j].l)+1); 46 } 47 for(int i=1,j=1;i<=n;i++) 48 { 49 while(j<=m&&a[j].l+a[j].r<=(i<<1)) j++; 50 pre[i]=j-1; 51 } 52 53 int ans=0; 54 for(int i=1;i+k-1<=n;i++) 55 { 56 for(int j=i;j+k-1<=n;j++) 57 { 58 int mid=(i+j+k-1)/2; 59 int res=w[i][pre[mid]]+w[j][m]-w[j][pre[mid]]; 60 ans=max(ans,res); 61 } 62 } 63 printf("%d ",ans); 64 return 0; 65 }