题意:给你n个活动的起止时间,要你从中选一些活动在2个会场安排(不能有两个活动在两个会场同时进行),使活动较少的会场活动数最大,以及在某个活动必须选择的前提下,求该答案。
思路:由于n很小,时间很大,先将时间离散化,num[l][r]表示全部在[l,r]内的活动个数,pre[i][j]表示前i的时间内给一边j个另一边最多有几个,则用1<=k<=i更新pre[i][j]=max(pre[k][j]+num[k][j],pre[k][j-num[k][i]]),第一问答案是min(pre[time][k],k)中的最大值
第二问,相当于一段区间s[i],t[i]必选,对于l<=s[i],r>=t[i],算出f[l][r] = min(x+y,pre[l][x]+num[l][r]+suf[r][y])中的最大值,x+y关于x,y单增,pre[l][x]+num[l][r]+suf[r][y]关于x,y单减,x,y不会同时变大或变小,所以从小到大枚举x时,y从大到小...
1 #include<bits/stdc++.h> 2 #define fo(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout); 3 using namespace std; 4 inline int read(){ 5 char ch=getchar(); 6 int res=0,f=1; 7 while(!isdigit(ch))f^=(ch=='-'),ch=getchar(); 8 while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar(); 9 return res*f; 10 } 11 const int N=405; 12 int n,s[N],t[N],a[N],cnt,pre[N][N],suf[N][N],f[N][N],num[N][N]; 13 inline void chemx(int &a,int b){ 14 a=a>b?a:b; 15 } 16 inline void chemn(int &a,int b){ 17 a=a>b?b:a; 18 } 19 #define calc(a,b) (min((a+b),(pre[l][a]+num[l][r]+suf[r][b]))) 20 int main(){ 21 fo("noi2011_show"); 22 n=read(); 23 for(int i=1;i<=n;i++)s[i]=read(),a[++cnt]=s[i],t[i]=read()+s[i],a[++cnt]=t[i]; 24 sort(a+1,a+cnt+1); 25 cnt=unique(a+1,a+cnt+1)-a-1; 26 for(int i=1;i<=n;i++){ 27 s[i]=lower_bound(a+1,a+cnt+1,s[i])-a; 28 t[i]=lower_bound(a+1,a+cnt+1,t[i])-a; 29 for(int l=1;l<=s[i];l++) 30 for(int r=t[i];r<=cnt;r++)num[l][r]++; 31 } 32 for(int i=1;i<=cnt;i++) 33 for(int j=1;j<=n;j++)pre[i][j]=suf[i][j]=-1e9; 34 for(int i=1;i<=cnt;i++) 35 for(int j=0;j<=num[1][i];j++) 36 for(int k=1;k<=i;k++){ 37 chemx(pre[i][j],pre[k][j]+num[k][i]); 38 if(j>=num[k][i])chemx(pre[i][j],pre[k][j-num[k][i]]); 39 } 40 for(int i=cnt;i;i--) 41 for(int j=0;j<=num[i][cnt];j++) 42 for(int k=cnt;k>=i;k--){ 43 chemx(suf[i][j],suf[k][j]+num[i][k]); 44 if(j>=num[i][k])chemx(suf[i][j],max(suf[k][j]+num[i][k],suf[k][j-num[i][k]])); 45 } 46 for(int l=1;l<=cnt;l++){ 47 for(int r=l;r<=cnt;r++){ 48 for(int x=0,y=num[r][cnt];x<=num[1][l];x++){ 49 while(y&&calc(x,y)<=calc(x,y-1))y--; 50 chemx(f[l][r],calc(x,y)); 51 } 52 } 53 } 54 int ans=0; 55 for(int i=1;i<=cnt;i++)for(int j=1;j<=num[1][i];j++)chemx(ans,min(pre[i][j],j)); 56 cout<<ans<<' '; 57 for(int i=1;i<=n;i++){ 58 int res=0; 59 for(int l=s[i];l;l--) 60 for(int r=t[i];r<=cnt;r++) 61 chemx(res,f[l][r]); 62 cout<<res<<' '; 63 } 64 }