zoukankan      html  css  js  c++  java
  • NOI2011 NOI嘉年华

    http://www.lydsy.com/JudgeOnline/problem.php?id=2436

    首先离散化,离散化后时间范围为[1,cnt]。

    求出H[i][j],表示时间范围在[i,j]的活动有多少个,可以在N^2的时间内解决。

    假设场地分别为A和B。

    我们容易知道,场地A和场地B的活动安排一定是这样的:

    他们的活动安排一定是这样间隔着的。

    我们求F[i][j],表示当时间<=i时,A场地有j个活动,B场地最多有多少个活动。

    我们这样记并不知道最后一个活动是在A场地还是B场地,但一定是这2种情况的最大值,也就是说:F[i][j]表示“当时间<=i时,A场地有j个活动且最后一个活动在A场地,B场地最多有多少个活动”和当时间<=i时,A场地有j个活动且最后一个活动在B场地,B场地最多有多少个活动"这两种情况的最大值。

    从小到大枚举i。

    先要倒序循环j,用F[i][j+1]更新F[i][j]:F[i][j]=max(F[i][j],F[i][j+1])。

    我们枚举j,向后递推,枚举k,

    如果接下来的[i+1,k]的时间区间内都是B场地在进行活动,我们可以转移到F[k][j]:F[k][j]=max(F[k][j],F[i][j]+H[i+1][k])。

    如果接下来的[i+1,k]的时间区间内都是A场地在进行活动,我们可以转移到F[k][j+H[i+1][k]]:F[k][j+H[i+1][k]]=max(F[k][j+H[i+1][k]],F[i][j])。

    这个可以在N^3的时间内解决。

    类似的,我们求G[i][j],表示当时间>=i时,A场地有j个活动,B场地最多有多少个活动,也是N^3的时间内解决。

    然后我们求T[i][j],表示[i,j]内的所有活动都在A场地时,活动相对较少的嘉年华的活动数量的最大值。

    很直接的一个想法是:

    $T[i][j]=max{min(x+y+H[i][j],F[i-1][x]+G[j+1][y])} (0leqslant xleqslant N,0leqslant yleqslant N)$

    但是这样算肯定是N^4的。

    我们发现,当x变大的时候,F[i-1][x]跟着变小:

    $min(x↑+y+H[i][j],F[i-1][x]↓+G[j+1][y])$

    如果y也跟着变大,G[j+1][y]跟着变小:

    $min(x↑+y↑+H[i][j],F[i-1][x]↓+G[j+1][y]↓)$

    由于我们取的是min,这样并没有什么卵用。

    所以y只能变小,G[j+1][y]跟着变大:

    $min(x↑+y↓+H[i][j],F[i-1][x]↓+G[j+1][y]↑)$

    所以随着x的递增,y递减。

    并且容易知道,这一定是个单峰的。

    所以可以N^3求出ans[i][j]。

    第1行的输出就是$max{min(i,F[cnt][i])}(0leqslant ileqslant N)$

    第i+1个输出就是$max(T[i][j])(1leqslant ileqslant l,rleqslant jleqslant cnt)$

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef complex<DB> CP;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define re(i,a,b)  for(i=a;i<=b;i++)
    #define red(i,a,b) for(i=a;i>=b;i--)
    #define fi first
    #define se second
    #define m_p(a,b) make_pair(a,b)
    #define SF scanf
    #define PF printf
    #define two(k) (1<<(k))
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    const DB EPS=1e-9;
    inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    inline int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    inline LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxN=200;
    const int maxcnt=2*maxN;
    
    int N;
    struct Tdata{int l,r,id;}a[maxN+10];
    
    int cnt,bak[2*maxN+100];
    
    int t[maxcnt+10];
    int H[maxcnt+10][maxcnt+10];
    
    inline bool cmpr(Tdata x,Tdata y){return x.r<y.r;}
    
    int F[maxcnt+10][maxN+10],G[maxcnt+10][maxN+10];
    
    int T[maxcnt+10][maxcnt+10];
    
    int ans,res[maxN+10];
    
    int main()
      {
          /*freopen("show.in","r",stdin);
          freopen("show.out","w",stdout);*/
          int i,j,k;
          N=gint();
          re(i,1,N)a[i].l=gint(),a[i].r=a[i].l+gint()-1,a[i].id=i;
          re(i,1,N)bak[++cnt]=a[i].l,bak[++cnt]=a[i].r;
          sort(bak+1,bak+cnt+1);
          cnt=unique(bak+1,bak+cnt+1)-bak-1;
          re(i,1,N)a[i].l=lower_bound(bak+1,bak+cnt+1,a[i].l)-bak,a[i].r=lower_bound(bak+1,bak+cnt+1,a[i].r)-bak;
          
          sort(a+1,a+N+1,cmpr);
          int head=1;
          re(i,1,cnt)
            {
                while(head<=N && a[head].r<=i)t[a[head].l]++,head++;
                int sum=0;
                red(j,i,1)sum+=t[j],H[j][i]=sum;
            }
          
          mmst(F,-1);
          F[0][0]=0;
          re(i,0,cnt-1)
            {
                red(j,N-1,0)upmax(F[i][j],F[i][j+1]);
                re(j,0,N)
                {
                    if(F[i][j]!=-1)re(k,i+1,cnt)upmax(F[k][j],F[i][j]+H[i+1][k]);
                    if(F[i][j]!=-1)re(k,i+1,cnt)upmax(F[k][j+H[i+1][k]],F[i][j]);
                }
            }
          
          mmst(G,-1);
          G[cnt+1][0]=0;
          red(i,cnt+1,2)
            {
                red(j,N-1,0)upmax(G[i][j],G[i][j+1]);
                re(j,0,N)
                {
                    if(G[i][j]!=-1)re(k,1,i-1)upmax(G[k][j],G[i][j]+H[k][i-1]);
                    if(G[i][j]!=-1)re(k,1,i-1)upmax(G[k][j+H[k][i-1]],G[i][j]);
                }
            }
          
          ans=0;
          re(j,0,N)upmax(ans,min(j,F[cnt][j]));
          cout<<ans<<endl;
          
          re(i,1,cnt)re(j,i,cnt)
            {
                T[i][j]=0;
                /*int x,y;
                re(x,0,N)re(y,0,N)
                  if(F[i-1][x]!=-1 && G[j+1][y]!=-1)
                    upmax(T[i][j],min(x+y+H[i][j],F[i-1][x]+G[j+1][y]));*/
                int x,y=N;
                while(y-1>=0 && G[j+1][y]==-1)y--;
                re(x,0,N)
                  {
                      if(F[i-1][x]==-1)continue;
                      while(y-1>=0 && min(x+y+H[i][j],F[i-1][x]+G[j+1][y])<=min(x+y-1+H[i][j],F[i-1][x]+G[j+1][y-1]))y--;
                      upmax(T[i][j],min(x+y+H[i][j],F[i-1][x]+G[j+1][y]));
                  }
            }
          
          re(i,1,N)
            {
                int l=a[i].l,r=a[i].r,id=a[i].id;
                res[id]=0;
                re(j,1,l)re(k,r,cnt)upmax(res[id],T[j][k]);
            }
          
          re(i,1,N)cout<<res[i]<<endl;
          
          return 0;
      }
    View Code
  • 相关阅读:
    linux一键安装filemanager和caddy
    搭建owncloud
    Linux下解压命令大全
    linux虚拟机调整分辨率
    [Javascript] ==与===区别
    [转]ActiveX控件安全初始化之一:实现ISafeObject接口
    C# 温故而知新:Stream篇(—)
    [转]C# 温故而知新:Stream篇(二)
    【转】C# 温故而知新:Stream篇(三)
    [转]在企业应用开发中遵循开源协议
  • 原文地址:https://www.cnblogs.com/maijing/p/4700986.html
Copyright © 2011-2022 走看看