zoukankan      html  css  js  c++  java
  • [NOI2011]Noi嘉年华

    题目描述

    NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办。每个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办。

    现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个活动的起始时间为 Si,活动的持续时间为Ti。这些活动都可以安排到任意一个嘉年华的会场,也可以不安排。

    小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。

    另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相对较少的嘉年华的活动数量最大。

    此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第i 个活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华的活动数量的最大值。

    输入输出格式

    输入格式:

    输入的第一行包含一个整数 n,表示申请的活动个数。

    接下来 n 行描述所有活动,其中第 i 行包含两个整数 Si、Ti,表示第 i 个活动从时刻Si开始,持续 Ti的时间。

    输出格式:

    输出的第一行包含一个整数,表示在没有任何限制的情况下,活动较少的嘉年华的活动数的最大值。

    接下来 n 行每行一个整数,其中第 i 行的整数表示在必须选择第 i 个活动的前提下,活动较少的嘉年华的活动数的最大值。

    输入输出样例

    输入样例#1:
    5 
    8 2 
    1 5 
    5 3 
    3 2 
    5 3 
    输出样例#1:
    2 
    2 
    1 
    2 
    2 
    2 

    说明

    【样例说明】

    在没有任何限制的情况下,最优安排可以在一个嘉年华安排活动1, 4,而在另一个嘉年华安排活动3, 5,活动2不安排。

    如果输出格式不正确(比如输出不足n+1行),得0分;

    如果输出文件第一行不正确,而且后n行至少有一行不正确,得0分;

    如果输出文件第一行正确,但后n行至少有一行不正确,得4分;

    如果输出文件第一行不正确,但后n行均正确,得6分;

    如果输出文件中的n+1行均正确,得10分。

     首先这道题每个点都给了4分的部分分.

    那么先考虑40分的,就是没有限制的情况.
    首先要将时间离散化.
    先预处理一个东西,in[i][j]表示在时间[i,j]只内的活动的数量.这个怎么暴力怎么搞.
    f[i][j]表示时间到了i,一个选了j个活动,另一个的最大值.
    那么转移就是f[i][j]=max(min(f[k][j]+in[k+1][i],f[i][j-in[k+1][i])).
    就是枚举这一次选的哪些区间,是放到哪个嘉年华中.
    然后40分就到手了..
    考虑剩下的60.
    每次限制了一个区间必须选.
    那么将状态转化一下,num[i][j]表示必须选[i,j]内的区间,且没有其他选了的越过这个区间
    的最大值.
    g[i][j]表示时间从后面到了i,一个选了j个活动,另一个的最大值.
    这个和f就是反着的.
    那么num[i][j]=max(min(x+y+in[i][j],f[i-1][x]+g[j+1][y])).
    这样是n^4,要考虑怎么优化.
    可以看出来这个式子是具有单调性的.
    x增大时,y只有减小才能取得更大的答案.
    所以就可以搞两个指针扫一遍即可,哪边大往哪边走.
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<string>
     6 #include<algorithm>
     7 #include<map>
     8 #include<complex>
     9 #include<queue>
    10 #include<stack>
    11 #include<cmath>
    12 #include<set>
    13 #include<vector>
    14 #define maxn 210
    15 using namespace std;
    16 struct data{
    17   int l,r;
    18 }k[maxn];
    19 int li[maxn*2],in[maxn*2][maxn*2],f[maxn*2][maxn],g[maxn*2][maxn],num[maxn*2][maxn*2],ans=0;
    20 int main(){
    21   int n,tot=0;
    22   scanf("%d",&n);
    23   for(int i=1;i<=n;i++)
    24     scanf("%d%d",&k[i].l,&k[i].r),k[i].r=k[i].l+k[i].r-1,li[++tot]=k[i].l,li[++tot]=k[i].r;
    25   sort(li+1,li+tot+1);
    26   int p=unique(li+1,li+tot+1)-li-1;
    27   for(int i=1;i<=n;i++){
    28     k[i].l=lower_bound(li+1,li+p+1,k[i].l)-li;
    29     k[i].r=lower_bound(li+1,li+p+1,k[i].r)-li;
    30   }
    31   for(int i=1;i<=p;i++)
    32     for(int j=i;j<=p;j++)
    33       for(int l=1;l<=n;l++)
    34     if(k[l].l>=i && k[l].r<=j) in[i][j]++;
    35   memset(f,-127/3,sizeof(f));memset(g,-127/3,sizeof(g));
    36   for(int i=0;i<=p+1;i++)
    37     f[i][0]=0,g[i][0]=0;
    38   f[1][0]=in[1][1],f[1][in[1][1]]=0;
    39   g[p][0]=in[p][p],g[p][in[p][p]]=0;
    40   for(int i=0;i<=p+1;i++)
    41     for(int j=0;j<=n;j++)
    42       for(int k=0;k<i;k++){
    43     int l=max(f[k][j]+in[k+1][i],(j-in[k+1][i]>=0)?f[k][j-in[k+1][i]]:0);
    44     f[i][j]=max(f[i][j],l);
    45     ans=max(ans,min(j,f[i][j]));
    46       }
    47   printf("%d
    ",ans);
    48   for(int i=p+1;i>=0;i--)
    49     for(int j=0;j<=n;j++)
    50       for(int k=p+1;k>i;k--){
    51     int l=max(g[k][j]+in[i][k-1],(j-in[i][k-1]>=0)?g[k][j-in[i][k-1]]:0);
    52     g[i][j]=max(g[i][j],l);
    53       }
    54   memset(num,-127/3,sizeof(num));
    55   for(int i=0;i<=p+1;i++)
    56     for(int j=i;j<=p+1;j++){
    57       int l=0,r=n;
    58       while(l<=n && r>=0){
    59     int x=min(l+1+r+in[i][j],f[i-1][l+1]+g[j+1][r]);
    60     int y=min(l+r-1+in[i][j],f[i-1][l]+g[j+1][r-1]);
    61     //if(max(x,y)<num[i][j]) break;
    62     if(x<y) r--,num[i][j]=max(num[i][j],y);
    63     else l++,num[i][j]=max(num[i][j],x);
    64       }
    65       //num[i][j]=ans;
    66     }
    67   for(int i=1;i<=n;i++){
    68     ans=0;
    69     for(int j=0;j<=k[i].l;j++)
    70       for(int w=k[i].r;w<=p+1;w++)
    71     ans=max(ans,num[j][w]);
    72     printf("%d
    ",ans);
    73   }
    74   return 0;
    75 }
    
    
    
     
  • 相关阅读:
    关于OI的文学作品
    HBOI 2020 游记
    从0开始的字符串生活(选手命要没了)
    近两年HBOI选做
    NOI online #3
    2020年“美团杯”程序设计挑战赛题解(目前只有测试赛)
    退群咕咕墙
    JS 获得当前地址栏url
    你了解getBoundingClientRect()?
    字符串与数字相加
  • 原文地址:https://www.cnblogs.com/pantakill/p/7502642.html
Copyright © 2011-2022 走看看