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

    链接:https://www.luogu.org/problemnew/show/P3537

    有n件物品,每件物品有三个属性a[i], b[i], c[i] (a[i]<b[i])。

    再给出q个询问,每个询问由非负整数m, k, s组成,问是否能够选出某些物品使得:

    1. 对于每个选的物品i,满足a[i]<=m且b[i]>m+s。

    2. 所有选出物品的c[i]的和正好是k。

    输入输出格式

    输入格式:

    n ( 1n1 000 ) 

    Those items are described in the nn lines that follow.

    c a b(1ci1 000 ,1ai<bi10e9 )

    p (1p1 000 000 ),

    m k s 1m,j10^9 , 1kj, sj100 000

    输出格式:

    For each plan put forward by the gang determine if it is feasible, i.e., whether it is possible to steal items of total worth exactly k_jkj and escape before anyone asks for their belongings.

    If the plan is feasible, your program should print the word TAK (Polish for yes) on the standard output, otherwise it should print NIE (Polish for no).

    输入输出样例

    输入样例#1: 复制
    5
    6 2 7
    5 4 9
    1 2 4
    2 5 8
    1 3 9
    5
    2 7 1
    2 7 2
    3 2 0
    5 7 2
    4 1 5
    输出样例#1: 复制
    TAK
    NIE
    TAK
    TAK
    NIE

    题解:离线

    我们把所有的 mm 和所有的ai 从小到大排序,然后就是一个背包问题了,因为这样我们做到一边把物品放入背包一边去处理这个询问。

    定义fi 表示当物品的和为 i 时在所有的方案中,使得最小的 b 最大的方案中的 b 值。(这话有些绕口)

    然后接下来我们只要判断一下 fi 是否大于m+s 即可。

    注意边界问题,我开始漏算了M巨大时的情况,和今天早上一样算了还=后面一截

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1005, M = 1000005;
    #define For(a, b, c) for(int a = b; a <= c; a++)
    struct Point{int a, b, c;}p[N];
    struct Query{int m, s, k, id;}q[M];
    bool cmp1(Point A, Point B){
        return A.a < B.a;
    }
    bool cmp2(Query A, Query B){
        return A.m < B.m;
    }
    int ans[M], dp[M];
    int main(){
        
        //freopen("dt.in","r",stdin);
        //freopen("my.out","w",stdout);
        int m, n;
        scanf("%d", &n);
        For(i, 1, n)scanf("%d%d%d", &p[i].c, &p[i].a, &p[i].b);
        sort(p+1, p+1+n, cmp1);
        scanf("%d", &m);
        For(i, 1, m)scanf("%d%d%d", &q[i].m, &q[i].k, &q[i].s), q[i].id = i;
        sort(q+1, q+1+m, cmp2);
        dp[0] = 1e9 + 100;
        int nlst = 1, lst = 1;
        int limit = q[1].m;
        p[n+1].a = dp[0];
        bool fg = 0;
        int j;
        for(int i = nlst; i <= n;){
            //cout<<i<<" "<<nlst<<endl;
            while(p[i].a <= limit){
                for(int j = 100000; j >= p[i].c; j--)
                    dp[j] = max(dp[j], min(dp[j - p[i].c], p[i].b));
                i++;
            }
            nlst = i;
            for( j = lst; q[j].m == q[lst].m; j++){
                int id = q[j].id;
                if(q[j].m + q[j].s < dp[q[j].k])ans[id] = 1;
                //else ans[id] = -1;
            }
            lst = j; limit = q[lst].m;
            if(lst == m + 1)break;
            //fprintf(stderr, "%d
    ", lst);
        }
        for( ; j <= m; j++)
            if(dp[q[j].k] > q[j].m + q[j].s)ans[q[j].id] = 1;
        for(int i = 1; i <= m; i++)
            if(ans[i] == 1)puts("TAK");
            else puts("NIE");
         
    }
    View Code
  • 相关阅读:
    页面性能优化之内容加载优化(转)
    (Windbg调试六)c++句柄泄漏问题定位
    (Windbg调试五)C++内存越界导致的std::map异常
    (Windbg调试四)C++死锁问题定位与分析
    (Windbg调试三)C++ delete指针后依然可以访问的问题
    (Windbg调试二)Windows下c++程序崩溃问题定位
    (Windbg调试一)minidump崩溃捕捉
    WinDbg调试:配置和查看符号
    为WinDbg设置符号文件路径
    Windbg符号与源码 《第二篇》
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9483305.html
Copyright © 2011-2022 走看看