zoukankan      html  css  js  c++  java
  • 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;
    }

    心如花木,向阳而生。
  • 相关阅读:
    POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
    SPOJ
    POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串
    POJ3261 Milk Patterns —— 后缀数组 出现k次且可重叠的最长子串
    POJ1743 Musical Theme —— 后缀数组 重复出现且不重叠的最长子串
    SPOJ
    AC自动机小结
    HDU3247 Resource Archiver —— AC自动机 + BFS最短路 + 状压DP
    POJ1625 Censored! —— AC自动机 + DP + 大数
    Herding
  • 原文地址:https://www.cnblogs.com/LLppdd/p/9184988.html
Copyright © 2011-2022 走看看