bzoj 2683 简单题 cdq分治

题面

题目传送门

解法

可以离线,那么就是非常简单的cdq分治了

只要把询问拆成4个,然后就变成了一个三维偏序问题

时间复杂度:\(O(q\ log^2\ n)\)

代码

#include <bits/stdc++.h>
#define int long long
#define N 1000010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f;
}
struct Node {
    int op, tim, x, y, v;
    bool operator < (const Node &a) const {
        return x < a.x;
    }
} a[N], t[N];
int n, f[N], ans[N];
int lowbit(int x) {return x & -x;}
void modify(int x, int v) {
    for (int i = x; i <= n; i += lowbit(i))
        f[i] += v;
}
int query(int x) {
    int ret = 0;
    for (int i = x; i; i -= lowbit(i))
        ret += f[i];
    return ret;
}
void cdq(int l, int r) {
    if (l == r) return;
    int mid = (l + r) >> 1, tx = l, ty = mid + 1;
    for (int i = l; i <= r; i++)
        if (a[i].tim <= mid) t[tx++] = a[i];
            else t[ty++] = a[i];
    for (int i = l; i <= r; i++) a[i] = t[i];
    tx = l, ty = mid + 1;
    while (ty <= r) {
        while (tx <= mid && a[tx].x <= a[ty].x) {
            if (a[tx].op == 1) modify(a[tx].y, a[tx].v);
            tx++;
        }
        if (a[ty].op == 2) ans[a[ty].v] += query(a[ty].y);
        if (a[ty].op == 3) ans[a[ty].v] -= query(a[ty].y);
        ty++;
    }
    for (int i = l; i < tx; i++) if (a[i].op == 1) modify(a[i].y, -a[i].v);
    cdq(l, mid), cdq(mid + 1, r);
}
main() {
    read(n);
    int len = 0, cntq = 0, op; read(op);
    while (op != 3) {
        if (op == 1) {
            int x, y, v;
            read(x), read(y), read(v);
            a[++len] = (Node) {op, len, x, y, v};
        } else {
            int x1, y1, x2, y2;
            read(x1), read(y1), read(x2), read(y2);
            a[++len] = (Node) {2, len, x2, y2, ++cntq};
            a[++len] = (Node) {3, len, x1 - 1, y2, cntq};
            a[++len] = (Node) {3, len, x2, y1 - 1, cntq};
            a[++len] = (Node) {2, len, x1 - 1, y1 - 1, cntq};
        }
        read(op);
    }
    sort(a + 1, a + len + 1);
    cdq(1, len);
    for (int i = 1; i <= cntq; i++) cout << ans[i] << "\n";
    return 0;
}

原文地址:https://www.cnblogs.com/copperoxide/p/9478324.html

时间: 2025-01-06 01:31:06

bzoj 2683 简单题 cdq分治的相关文章

BZOJ 2683 简单题 ——CDQ分治

简单题 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 2000005 int sum[maxn]; void a

BZOJ 2683 简单题 cdq分治+树状数组

题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后,二维的数据结构是显然不能过的,于是我们可能会考虑把一维排序之后另一位上数据结构什么的,然而cdq分治却能够很好的体现它的作用. 首先,对于每一个询问求和,显然是x在它左边的并且出现时间在它之前的所有的change对他可能会有影响. 我们按照x第一关键字,y第二关键字,操作第三关键字来排序所有的询问,然后在cdq的时候,每次递归处理左半区间,按照x动态的将y这一列的值加到树状数组里,来更新右半边的所有询问,注意这

【BZOJ-1176&amp;2683】Mokia&amp;简单题 CDQ分治

1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1854  Solved: 821[Submit][Status][Discuss] Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

bzoj 2683: 简单题

2683: 简单题 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1779  Solved: 720[Submit][Status][Discuss] Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数字加上A 2 x1 y1 x2 y2 1<=x1<= x2<=N 1<

bzoj2683简单题 cdq分治

2683: 简单题 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1803  Solved: 731[Submit][Status][Discuss] Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数字加上A 2 x1 y1 x2 y2 1<=x1<= x2<=N 1<

Bzoj2683 简单题 [CDQ分治]

Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1071  Solved: 428 Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数字加上A 2 x1 y1 x2 y2 1<=x1<= x2<=N 1<=y1<= y2<=N 输出x1 y1 x2 y2这个矩形

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组

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 输入

BZOJ 1176 Mokia(cdq分治,解决一类在线查询问题)

题意:维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. 这题在bz是贵族题= =,没有链接了 解法:cdq分治,第一维是时间t,第二维是x,第三维是y:每个操作看作一个三维序(t, x, y):假设修改操作是(t, x, y),两个查询操作分别是(t1, x1, y1) 和 (t1, x2, y2):实际上就要问,有多少个修改操作,满足t<=t1,x1<=x&

BZOJ 1176 [Balkan2007]Mokia CDQ分治

题目大意: 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. POJ1195的加强版 没记错的话上午这题还没有中文题目描述的说0.0 好迅速 首先这题看到W就知道二维树状数组挂了 看到M就发现离散化了也搞不了 0.0 这题似乎是CDQ分治被发现之后第二个解决的题目...不过只有会员才知道的世界,今天反应过来刷刷... 修改和询问放在一起分治,一个询问拆分成4个,树状数组处