POJ 1769_Minimizing maximizer

题意:

一系列m个1~n区间,每个区间固定对某个子区间进行排序,顺序选择若干区间,使最终覆盖所有区间。

分析:

computes the length of the shortest subsequence of the initial sequence of sorters still producing correct results for all possible input data

要想明白几点:

  • 输入时最大值的位置情况不确定,但是只要求出最大值在第一个位置的最短sorter序列,其他位置的情况就均满足了。
  • 怎样删才能保证正常输出?就是最大值在删去中间几个sorter之后位置不发生改变。

dp[j] 表示最大值到达 j 位置所需的最少sorter个数,有两种情况:

  • 在第i1个sorter中最大值k,满足 ai1k<bi1 ,那么在第 i 个sorter中最大值则被移动到bi1的位置。

    • 否则,最大值位置不发生改变,则可以省去第 i1 个sorter
    • 可以得到状态转移方程:

      dp[b[i]] = min(dp[b[i]], dp[j] + 1);  a[i]<= j < b[i]

      然后就TLE了。。。。然后就一脸懵逼.jpg


      m个sorter肯定要遍历一遍,就只能在最少次数的获取上优化了。不停的获取最少次数又不停的更新到 dp[b[i]] ,单节点更新问题,可以用线段树优化,时间复杂度降为 O(mlogn)

      代码:

      #include<cstdio>
      #define min( a, c ) (a)<(c)?(a):(c)
      const int maxn = 500005, INF = 0x3fffffff;
      int a[maxn], b[maxn], m[3*maxn];
      void build(int k, int l, int r)
      {
          m[k] = INF;
          if(l == r - 1) return;
          build(k * 2 + 1,l, (l+r)/2);
          build(k * 2 + 2, (l+r)/2, r);
      }
      void update(int a, int  x, int k, int l, int r)
      {
            m[k] = min(x, m[k]);
            if(l < r-1){
              int m = (l+r)/2;
              if(m > a) update(a, x, k * 2 + 1, l, m);
              else update(a, x, k * 2 + 2, m, r);
          }
      }
      int query(int a, int b, int k, int l, int r)
      {
          if(a >= r|| b <= l) return INF;
          else if(a <= l && r <= b) return m[k];
          else {
              int ta = query(a, b, k * 2 + 1, l, (l+r)/2);
              int tb = query(a, b, k * 2 + 2, (l + r)/2, r);
              return min(ta, tb);
          }
      }
      int main (void)
      {
          int n, _m;scanf("%d%d",&n,&_m);
          build(0, 0, n);
          update(0, 0, 0, 0, n);
          for(int i = 0; i < _m; i++) {
                  scanf("%d%d",&a[i],&b[i]);
                  int t = query(a[i]-1, b[i], 0, 0, n) + 1;
                  update(b[i]-1, t, 0, 0, n);
          }
          printf("%d\n",query(n-1, n, 0, 0, n));
      }
      

      选择合适的数据结构对dp进行优化,可以降低计算的复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值