码迷,mamicode.com
首页 > 其他好文 > 详细

Gym-101470C

时间:2021-03-12 12:40:39      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:hang   技术   png   tree   c++   res   strong   UNC   高度   

C - UFO

题意

给一个 \(n\times m\) 的矩形,代表对应位置方块的数目,现在进行 \(k\) 次激光攻击,每次激光攻击会在高度 \(h\) 处从 \(N,S,W,E\) 四个方向中的一个向对面发射激光,若命中一个块,则改方块消失,每次激光最多消灭 \(r\) 个方块。

攻击结束后,方块会掉落。问最后在 \(p \times p\) 的矩形内,最多有多少个方块

技术图片

\(1 \le n*m \le 1e6\) , \(1 \le r \le 10\) , \(1\le k\le 3e5\) , \(1 \le p \le min(n,m,10)\)

思路

用线段树模拟即可,每次找区间内第一个大于等于某个值的元素,或者最后一个大于等于某个元素(高度)的值,

最后做一个二维前缀和

#include<bits/stdc++.h>
using namespace std;

#define lo (o << 1)
#define ro (o << 1 | 1)
#define mid (l + r >> 1)
#define what(x) cerr << #x << " is " << x << endl;
#define getall(x,ed) cerr << #x << ": \t";debug(x,ed);
template<typename T>
void debug(T begin, T ed) {
    for (T i = begin;i != ed;i++)cout << *i << ‘\t‘;cout << ‘\n‘;
}


typedef long long ll;

int n, m, r, k, p;
vector<vector<int>>mp, RTree, CTree;
vector<vector<ll>>qzh;
void build(vector<int>& Tree, int o, int l, int r, int type, int idx) {
    if (l == r) {
        if (type == 0) {
            Tree[o] = mp[idx][l];
        }
        else {
            Tree[o] = mp[l][idx];
        }
        return;
    }
    build(Tree, lo, l, mid, type, idx);build(Tree, ro, mid + 1, r, type, idx);
    Tree[o] = max(Tree[lo], Tree[ro]);
}
int query_first(vector<int>& Tree, int L, int R, int tar, int o, int l, int r) {
    if(l == r){
        if(Tree[o] >= tar)return l;
        else return -1;
    }
    if (L <= l and r <= R) {
        if(Tree[o] < tar) return -1;
    }
    int ans = -1;
    if (L <= mid) ans = query_first(Tree, L, R, tar, lo, l, mid);
    if (ans != -1)return ans;
    if (R > mid)ans = query_first(Tree, L, R, tar, ro, mid + 1, r);
    return ans;
}
int query_last(vector<int>& Tree, int L, int R, int tar, int o, int l, int r) {
    if (l == r) {
        if (Tree[o] >= tar)return l;
        else return -1;
    }
    if (L <= l and r <= R) {
        if (Tree[o] < tar) return -1;
    }
    int ans = -1;
    if (R > mid)ans = query_last(Tree, L, R, tar, ro, mid + 1, r);
    if (ans != -1)return ans;
    if (L <= mid) ans = query_last(Tree, L, R, tar, lo, l, mid);
    return ans;
}
void updtTree(vector<int>& Tree, int pos, int o, int l, int r) {
    if (l == r) {
        Tree[o]--;
        return;
    }
    if (pos <= mid)updtTree(Tree, pos, lo, l, mid);
    else updtTree(Tree, pos, ro, mid + 1, r);
    Tree[o] = max(Tree[lo], Tree[ro]);
}
void modify(int r, int c) {
    updtTree(RTree[r], c, 1, 1, m);
    updtTree(CTree[c], r, 1, 1, n);
    mp[r][c]--;
}

int main() {
#ifdef ONLINE_JUDGE
    freopen("c.in", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif
    scanf("%d%d%d%d%d", &n, &m, &r, &k, &p);
    mp.resize(n + 1, vector<int>(m + 1, 0));
    for (int i = 1;i <= n;i++)for (int j = 1;j <= m;j++)scanf("%d", &mp[i][j]);
    RTree.resize(n + 1, vector<int>((m + 1) << 2, 0));
    CTree.resize(m + 1, vector<int>((n + 1) << 2, 0));

    for (int i = 1;i <= n;i++)build(RTree[i], 1, 1, m, 0, i);
    for (int i = 1;i <= m;i++)build(CTree[i], 1, 1, n, 1, i);

    //puts("build");

    while (k--) {
        char dir[2];int pos, h;
        scanf("%s%d%d", dir, &pos, &h);
        if (*dir == ‘N‘) {
            int L = 1, R = n;
            for (int k = 1;k <= r;k++) {
                int p = query_first(CTree[pos], L, R, h, 1, 1, n);
                if (p == -1)break;
                modify(p, pos);
                L = p + 1;
            }
        }
        else if (*dir == ‘S‘) {
            int L = 1, R = n;
            for (int k = 1;k <= r;k++) {
                int p = query_last(CTree[pos], L, R, h, 1, 1, n);
                if (p == -1)break;
                modify(p, pos);
                R = p - 1;
            }
        }
        else if (*dir == ‘W‘) {
            int L = 1, R = m;
            for (int k = 1;k <= r;k++) {
                int p = query_first(RTree[pos], L, R, h, 1, 1, m);
                if (p == -1)break;
                modify(pos, p);
                L = p + 1;
            }
        }
        else if (*dir == ‘E‘) {
            int L = 1, R = m;
            for (int k = 1;k <= r;k++) {
                //what(pos);what(h);
                int p = query_last(RTree[pos], L, R, h, 1, 1, m);
                if (p == -1)break;
                modify(pos, p);
                R = p - 1;
            }
        }

    }
    //puts("ok");
    qzh.resize(n + 1, vector<ll>(m + 1, 0));
    // for(int i = 1;i <= n;i++){
    //     for(int j = 1;j <= m;j++){
    //         cout << mp[i][j] << " ";
    //     }cout << ‘\n‘;
    // }
    //getall(mp[1].begin() + 1, mp[1].end());
    ll ans = 0;
    for (int i = 1;i <= n;i++) {
        for (int j = 1;j <= m;j++) {
            qzh[i][j] = mp[i][j] + qzh[i - 1][j] + qzh[i][j - 1] - qzh[i - 1][j - 1];
            if (i >= p and j >= p) {
                ans = max(ans, qzh[i][j] - qzh[i - p][j] - qzh[i][j - p] + qzh[i - p][j - p]);
            }
        }
    }
    
    printf("%lld\n", ans);;
}

Gym-101470C

标签:hang   技术   png   tree   c++   res   strong   UNC   高度   

原文地址:https://www.cnblogs.com/sduwh/p/14516179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!