• BZOJ1176 [Balkan2007]Mokia 【CDQ分治】


    题目

    维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

    输入格式

    第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

    接下来每行为一下三种输入之一(不包含引号):

    “1 x y a”

    “2 x1 y1 x2 y2”

    “3”

    输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

    输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出

    输入3:表示输入结束

    输出格式

    对于每个输入2,输出一行,即输入2的答案

    输入样例

    0 4

    1 2 3 3

    2 1 1 3 3

    1 2 2 2

    2 2 2 3 4

    3

    输出样例

    3

    5

    提示

    保证答案不会超过int范围

    题解

    CDQ分治
    每个询问分解成4个前缀和
    然后每个询问或修改就有三维(x,y,t)
    一个询问被一个修改影响当且仅当t1 > t2 且x1 >= x2 且 y1 >= y2
    可以上CDQ分治
    【可以顺便吧2683A了】

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define lbt(x) (x & -x)
    using namespace std;
    const int maxn = 200005,maxm = 2000005,INF = 1000000000;
    inline int RD(){
        int out = 0,flag = 1; char c = getchar();
        while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
        while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
        return out * flag;
    }
    LL S[maxm],N,s;
    void add(int u,int v){while (u <= N) S[u] += v,u += lbt(u);}
    LL sum(int u){LL ans = 0; while (u) ans += S[u],u -= lbt(u); return ans;}
    
    struct Que{LL x,y,id,v,pos,t;}Q[maxn],T[maxn];
    inline bool operator <(const Que& a,const Que& b){
        if (a.x == b.x && a.y == b.y) return a.t < b.t;
        if (a.x == b.x) return a.y < b.y;
        return a.x < b.x;
    }
    LL Qi = 0,ans[maxn];
    void CDQ(int l,int r){
        if (l == r) return;
        int mid = l + r >> 1,l1 = l,l2 = mid + 1;
        for (int i = l; i <= r; i++)
            if (Q[i].t <= mid && !Q[i].id) add(Q[i].y,Q[i].v);
            else if (Q[i].t > mid && Q[i].id) ans[Q[i].id] += Q[i].pos * sum(Q[i].y);
        for (int i = l; i <= r; i++){
            //printf("[%lld,%lld],id = %lld,t = %lld
    ",Q[i].x,Q[i].y,Q[i].id,Q[i].t);
            if (Q[i].t <= mid){
                T[l1++] = Q[i];
                if (!Q[i].id) add(Q[i].y,-Q[i].v);
            }
            else T[l2++] = Q[i];
        }
        for (int i = l; i <= r; i++) Q[i] = T[i];
        CDQ(l,mid); CDQ(mid + 1,r);
    }
    int main(){
        //freopen("in.txt","r",stdin);
        //freopen("out1.txt","w",stdout);
        s = RD(); N = RD();
        LL opt,a,b,c,d;
        while (true){
            opt = RD(); if (opt == 3) break;
            if (opt & 1){
                a = RD(),b = RD(),c = RD();
                Q[++Qi] = (Que){a,b,0,c,0,Qi};
            }else {
                a = RD(),b = RD(),c = RD(); d = RD();
                int pos = ++ans[0];
                Q[++Qi] = (Que){c,d,pos,0,1,Qi};
                Q[++Qi] = (Que){c,b - 1,pos,0,-1,Qi};
                Q[++Qi] = (Que){a - 1,d,pos,0,-1,Qi};
                Q[++Qi] = (Que){a - 1,b - 1,pos,0,1,Qi};
                ans[pos] = (c - a + 1) * (d - b + 1) * s;
            }
        }
        sort(Q + 1,Q + 1 + Qi);
        CDQ(1,Qi);
        REP(i,ans[0]) printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    寒假每日总结(八)
    寒假每日总结(七)
    寒假每日总结(六)
    2020-2.19
    2020-2.18
    寒假每日总结-2020.2.11
    寒假每日总结-2020.2.10
    寒假每日总结-2020.2.9
    寒假每日总结
    寒假每日总结——2020.2.6
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282712.html
Copyright © 2020-2023  润新知