zoukankan      html  css  js  c++  java
  • 导弹防御[差分]


    Solution

    因为B的防护罩开启 时间上的区间 已经确定, 所以只需要考虑A防护 时间上的区间 即可
    因为只需考虑A受到的伤害, 所以开始时将所有可能对A造成伤害的导弹保存, 其余不管
    现在手上就有了一个导弹序列, 那该怎么处理呢?

    对于一个即将击中A的导弹, 想要拦截它, 必须使用防御区间覆盖其所有落在A的时间点
    (由于导弹会反弹, 所以一个导弹可能会多次光临)

    暂且称导弹到达A的时刻为危险时刻

    可以使A的保护区间左端点从最早 危险时刻 至最晚 危险时刻遍历
    每次计算该区间拦截成功的导弹伤害, 用总伤害减去减免伤害即为受到的伤害

    此过程可以使用差分维护
    具体分两种情况讨论

    设该导弹到达的时刻为 uu, 导弹伤害为 ww, 导弹速度为 vv, 差分数组 CC

    • 反弹一次成功击中B, 此时只需要防御区间覆盖一个危险时刻uu即可, l=max{0,uTA}l = max{0, u-TA}
    • 反弹多次成功击中B, 此时需要防御区间覆盖这个导弹的危险时刻uu及衍生出的所有危险时刻, 可以O(1)O(1)计算出最后一个危险时刻为Temp=(X+TBuv2v+1)2v+uTemp = ( lfloorfrac{X+TB-u-v}{2v} floor+1)*2v+u, 于是 l=max{0,TempTA}l = max{0, Temp-TA}

    如图, P=X+TB(u+v)2v2vP = lfloorfrac{X+TB-(u+v)}{2v} floor*2v ,
    Temp=P+2v+u=(X+TBuv2v+1)2v+uTemp = P+2v+u = ( lfloorfrac{X+TB-u-v}{2v} floor+1)*2v+u
    在这里插入图片描述


    对于上方所有的l,ul, u, 都采取操作C[l]+=w,C[u+1]=wC[l] += w, C[u+1] -= w, 最后O(N)O(N)扫, 取最大减免伤害即可.


    Code

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 10005;
    typedef long long ll;
    
    int TA;
    int TB;
    int X;
    int N;
    int M;
    int cnt;
    
    struct Attack{
            int v, tim, w;
            Attack(int v=0, int tim=0, int w=0):v(v), tim(tim), w(w) {}
    } Atk[maxn << 2];
    
    struct Cha{ int tim, w; } C[maxn<<2];
    
    bool cmp(Cha a, Cha b){ return a.tim==b.tim?a.w<b.w:a.tim<b.tim; }
    
    void Work(){
            cnt = 0;
            scanf("%d%d%d", &X, &N, &M);
            int u, v, w;
            for(reg int i = 1; i <= N; i ++){
                    scanf("%d%d%d", &u, &v, &w);
                    if(u+v < X || u+v > X+TB) continue ;
                    Atk[++ cnt] = Attack(v, u+(v<<1), w);
            }
            for(reg int i = 1; i <= M; i ++){
                    scanf("%d%d%d", &u, &v, &w);
                    Atk[++ cnt] = Attack(v, u+v, w);
            }
            int tot = 0;
            int sum = 0;
            for(reg int i = 1; i <= cnt; i ++){
                    v = Atk[i].v, u = Atk[i].tim, w = Atk[i].w;
                    sum += w;
                    int l;
                    if(u+v < X || u+v > X+TB) l = std::max(0, u-TA);
                    else{
                            int Temp = ((X+TB-u-v)/v/2 + 1) * 2*v + u;
                            l = std::max(0, Temp-TA);
    //                        int t = (X+TB-u-v)/v/2;
    //                        l = std::max(u+v*2*(t+1)-TA, 0);
                    }
                    if(l > u) continue ;
                    C[++ tot] = (Cha){ u+1, -w };
                    C[++ tot] = (Cha){ l, w };
            }
            int Ans = 0, temp = 0;
            std::sort(C+1, C+tot+1, cmp);
            for(reg int i = 1; i <= tot; i ++){
                    temp += C[i].w;
                    Ans = std::max(temp, Ans);
            }
            if(sum < Ans) printf("Yes
    ");
            std::cout << sum - Ans << std::endl;
    //        printf("%lld
    ", sum - Ans);
    }
    
    int main(){
            freopen("missile.in", "r", stdin);
            freopen("missile.out", "w", stdout);
            while(~scanf("%d%d", &TA, &TB)) Work();
            return 0;
    }
    /*
    2 2
    2
    1 0
    1 1 10
    4 5
    3
    2 2
    1 2 10
    1 5 7
    1 3 2
    0 4 8
    */
    
  • 相关阅读:
    教务管理系统(node+express+mysql)
    poj 2485 Highways 超级大水题 kruscal
    HDU 1874 畅通工程续 + HDU 2544 最短路 最短路水题,floyd水
    HEX格式转BIN格式 MOT格式转BIN格式
    html的标签一共有多少个?
    同时存在n个线程(n>5),需要写入或者读取一个名为test.txt的文件
    poj 1258 AgriNet 水题三连发。。。又是kruscal
    招投标专家库
    poj 1789 kruscal水题
    仿Word自动套用格式,用CSS设置表格样式
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822652.html
Copyright © 2011-2022 走看看