• bzoj1176 [Balkan2007]Mokia


    [Balkan2007]Mokia

    Time Limit: 30 Sec Memory Limit: 162 MB

    Description

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

    Input

    第一行两个整数,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:表示输入结束

    Output

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

    Sample Input

    0 4

    1 2 3 3

    2 1 1 3 3

    1 2 2 2

    2 2 2 3 4

    3

    Sample Output

    3

    5

    HINT

    保证答案不会超过int范围


    CDQ分治了解一下。。。 这个东西有点厉害啊。。。离线操作总有一些好方法啊。。。 大概就是降维打击。。。 每次都只管前面一半对后面一半的贡献,然后分治。 其实还是降维打击最为致命啊 这道题是个入门题。。。。自己瞎yy了一波。。。我只是打错了 i 和 p2 就调了很久。。。但还是是 1A 的啦(傲娇~) 详细解法早就烂大街了。。。但是我看的是论文
    ```c++

    include<bits/stdc++.h>

    define lowbit(x) (x & (-x))

    using namespace std;
    const int maxn = 2e6 + 6;
    struct lpl{
    int mark, opt, x, y, id;
    }ini[200005], tmp[200005];
    int w, s, opt, q, cnt, ans[10005], tree[maxn];

    inline void SRT(int l, int r)
    {
    int mid = (l + r) >> 1;
    int p1 = l, p2 = mid + 1, p = l - 1;
    while(p1 <= mid && p2 <= r){
    if(p1 <= mid && p2 <= r && ini[p1].x <= ini[p2].x) tmp[++p] = ini[p1++];
    if(p1 <= mid && p2 <= r && ini[p1].x > ini[p2].x) tmp[++p] = ini[p2++];
    }
    for(int i = p1; i <= mid; ++i) tmp[++p] = ini[i];
    for(int i = p2; i <= r; ++i) tmp[++p] = ini[i];
    for(int i = l; i <= r; ++i) ini[i] = tmp[i];
    }

    inline void Modify(int t, int val)
    {
    if(!t) return;
    while(t < maxn){
    tree[t] += val; t += lowbit(t);
    }
    }

    inline int Query(int t)
    {
    int ret = 0;
    if(!t) return ret;
    while(t){
    ret += tree[t];
    t -= lowbit(t);
    }
    return ret;
    }

    void CDQ(int l, int r)
    {
    if(l == r) return;
    int mid = (l + r) >> 1;
    CDQ(l, mid); CDQ(mid + 1, r);
    SRT(l, mid); SRT(mid + 1, r);
    int p1 = l, p2 = mid + 1, tot = 0;
    while(p1 <= mid && p2 <= r){
    while(p1 <= mid && p2 <= r && ini[p1].x <= ini[p2].x){
    if(ini[p1].opt == 2){p1++; continue;}
    Modify(ini[p1].y, ini[p1].mark); tot++; tmp[tot] = ini[p1]; p1++;
    }
    if(p1 > mid || p2 > r) break;
    if(ini[p2].opt == 2){
    ans[ini[p2].id] += Query(ini[p2].y) * ini[p2].mark; p2++; continue;
    }
    p2++;
    }
    for(int i = p2; i <= r; ++i)
    if(ini[i].opt == 2)
    ans[ini[i].id] += Query(ini[i].y) * ini[i].mark;
    for(int i = 1; i <= tot; ++i)
    Modify(tmp[i].y, -tmp[i].mark);
    }

    int main()
    {
    int x1, x2, y1, y2;
    scanf("%d%d", &w, &s);
    while(1){
    scanf("%d", &opt);
    if(opt == 3) break;
    if(opt == 2){
    q++; scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    ini[++cnt].opt = 2; ini[cnt].mark = 1; ini[cnt].x = x2; ini[cnt].y = y2; ini[cnt].id = q;
    ini[++cnt].opt = 2; ini[cnt].mark = -1; ini[cnt].x = x1 - 1; ini[cnt].y = y2; ini[cnt].id = q;
    ini[++cnt].opt = 2; ini[cnt].mark = -1; ini[cnt].x = x2; ini[cnt].y = y1 - 1; ini[cnt].id = q;
    ini[++cnt].opt = 2; ini[cnt].mark = 1; ini[cnt].x = x1 - 1; ini[cnt].y = y1 - 1; ini[cnt].id = q;
    }
    if(opt == 1){
    ini[++cnt].opt = 1;
    scanf("%d%d%d", &ini[cnt].x, &ini[cnt].y, &ini[cnt].mark);
    }
    }
    CDQ(1, cnt);
    for(int i = 1; i <= q; ++i) printf("%d ", ans[i]);
    return 0;
    }

    心如花木,向阳而生。
  • 相关阅读:
    android RecyclerView smoothScrollToPosition 每次都能滚动到顶部
    android eventbus四种线程模型
    android代码设置主题无效setTheme
    Word备忘录
    Markdown基本语法
    游戏常用术语
    字体格式
    Excel备忘录
    离线方式快速安装python模块以及相关依赖模块
    kube-proxy
  • 原文地址:https://www.cnblogs.com/LLppdd/p/9184988.html
Copyright © 2020-2023  润新知