zoukankan      html  css  js  c++  java
  • [POI2012]SZA-Cloakroom

    嘟嘟嘟


    一道比较有意思的dp。


    这题关键在于状态的设计。如果像我一样令(dp[i][j])表示选到第(i)个物品,(sum c)能都等于(j)的话,那就是(O(qnk))了,怒拿一半分……
    正解应该是令(dp[i][j])表示选出的物品的(a)小于等于(i)(sum c)等于(j)时,(b)的最小值的最大值。
    然后我们可以离散化(a),再dp。
    但这样会MLE……
    所以还是离线吧:把询问按(m)排序,然后把所有小于等于(m)(a)的物品放进去dp,于是就有(dp[i][j] = max(dp[i][j], min(dp[i - 1][j - c[k]], b[k])))
    然后像背包一样省去第一维,倒着枚举。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxk = 2e5 + 5;
    const int maxn = 1e3 + 5;
    inline ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    inline void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    
    int n, Q, m, K, s;
    struct Node
    {
      int a, b, c, id;
      In bool operator < (const Node& oth)const
      {
        return a < oth.a;
      }
    }t[maxn], q[maxn * maxn];
    
    int dp[maxk];
    bool ans[maxn * maxn];
    
    int main()
    {
      n = read();
      for(int i = 1; i <= n; ++i)
        t[i].c = read(), t[i].a = read(), t[i].b = read();
      Q = read();
      for(int i = 1; i <= Q; ++i)
        q[i].a = read(), q[i].b = read(), q[i].c = read(), q[i].id = i;
      sort(t + 1, t + n + 1), sort(q + 1, q + Q + 1);
      dp[0] = INF;
      for(int i = 1, j = 1; i <= Q; ++i)
        {
          while(j <= n && t[j].a <= q[i].a)
    	{
    	  for(int k = 1e5; k >= t[j].c; --k)
    	    dp[k] = max(dp[k], min(dp[k - t[j].c], t[j].b));
    	  ++j;
    	}
          if(dp[q[i].b] > q[i].a + q[i].c) ans[q[i].id] = 1;
        }
      for(int i = 1; i <= Q; ++i) puts(ans[i] ? "TAK" : "NIE");
      return 0;
    }
    
  • 相关阅读:
    97. Interleaving String
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    94. Binary Tree Inorder Traversal
    odoo many2many字段 指定打开的form视图
    docker sentry 配置文件位置
    postgres 计算时差
    postgres 字符操作补位,字符切割
    postgres判断字符串是否为时间,数字
    odoo fields_view_get
  • 原文地址:https://www.cnblogs.com/mrclr/p/10630345.html
Copyright © 2011-2022 走看看