zoukankan      html  css  js  c++  java
  • CodeForces 846D. Monitor(二维线段树)

    题目大意:

    给予n,m,k,t 和 t 行i,j,val代表第i行j列的元素会在val天后损坏。

    求在整张(n*m)图中求一个k*k的区域的数全部损坏的最小天数。



    试了一下二维线段树,总结一下就是和一维的差别不大,从二叉树变成了四叉树(三维线段树岂不是要八叉树,丧心病狂)。

    总体上就是把一个长方形均分四块,然后总的节点数就是一个首项为[max(n*m)^2]公比为1/4的等比数列前若干项和,具体比例是多少可以求极限算一下。

    空间复杂度基本是O(max(n,m)²)的具体数据如下:
    Case total node input_n input_m total rec rec/node
    1 1398101 1024 1024 1048576 75%
    2 349525 512 512 262144 75%
    3 1398099 1024 512 524288 37.5%
    4 349519 500 500 250000 71.53%
    5 699051 1024 1 1024 0.1465%
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    const int mxn = 250000;
    #define inf 0x3f3f3f3f
    inline int son(int p,int x){
        return (p<<2)-2+x;
    }
    int n,m;
    struct Interval:public pair<short ,short >{
    #define l first
    #define r second
        Interval(short a, short b):pair<short ,short >(a,b){}
        short mid(){
            return ((r-l)>>1)+l;
        }
        short length(){
            return r-l+(short)1;
        }
        Interval left(){
            return Interval(l,mid());
        }
        Interval right(){
            return Interval(mid()+(short)1,r);
        }
        bool in(int L,int R){
            return l <= L and R <= r;
        }
        bool in(const Interval&temp){
            return in(temp.l,temp.r);
        }
        bool intersect(const Interval &k){
            return !( l > k.r || r < k.l );
        }
        void show(){
            cerr<<l<<" "<<r<<"
    ";
        }
    };
    int plant[505][505];
    int val[mxn<<2];
    void pushUp(int rt){
        for(int i = 0 ; i < 4 ; ++i){
            val[rt] = max(val[rt],val[son(rt,i)]);
        }
    }
    void buildTree(int rt,Interval x,Interval y){
        if(x.length() <= 0 or y.length() <=0)return;
        if(x.length()==1 and y.length() == 1){
            val[rt] = plant[x.l][y.l];
            return;
        }
        for(int i = 0; i < 4 ; ++i){
            buildTree(son(rt,i) , (i&1)?x.right():x.left(),(i&2)?y.right():y.left());
        }
        pushUp(rt);
    }
    Interval tarx(0,0),tary(0,0);
    int Query(int rt,Interval x,Interval y){
        if(tarx.in(x) and tary.in(y)){
            return val[rt];
        }
        if(!tary.intersect(y) or !tarx.intersect(x))return 0;
        int ret = 0;
        for(int i = 0 ; i < 4 ; ++i){
            ret = max(ret,Query(son(rt,i) , (i&1)?x.right():x.left(),(i&2)?y.right():y.left()));
        }
        return ret;
    }
    int Query(short begx, short begy,int k){
        tarx = Interval(begx,begx+(short)(k-1));
        tary = Interval(begy,begy+(short)(k-1));
        return Query(1,Interval(1,n),Interval(1,m));
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m;
        int k,t,x,y,a;
        cin>>k>>t;
        memset(plant,0x3f, sizeof(plant));
        while (t--){
            cin>>x>>y>>a;
            plant[x][y] = a;
        }
        int ans = inf;
        buildTree(1,Interval(1,n),Interval(1,m));
        for(int i = 1 ; i <= n-k+1;  ++i){
            for(int j = 1 ; j <= m-k+1; ++j){
                ans = min(ans,Query(i,j,k));
            }
        }
        if(ans!=inf){
            cout<<ans;
        }else cout<<-1;
    }
  • 相关阅读:
    CodeForces 19D Points (线段树+set)
    FZU 2105 Digits Count
    HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
    HDU 5634 Rikka with Phi (线段树)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
  • 原文地址:https://www.cnblogs.com/DevilInChina/p/9884121.html
Copyright © 2011-2022 走看看