zoukankan      html  css  js  c++  java
  • 【cdq分治】【P4390】[BOI2007]Mokia 摩基亚

    Description

    给你一个 (W~ imes~W) 的矩阵,每个点有权值,每次进行单点修改或者求某子矩阵内权值和,允许离线

    Input

    第一行是两个数字 (0) 和矩阵大小 (W)

    下面每行可能会出现如下参数

    (1,x,y,A) 单点修改格子 (x,y)(A)

    (2,x_1,y_1,x_2,y_2) 查询给定矩阵的权值和

    (3) 结束查询与修改

    Output

    对每个查询给出一行作为答案

    Hint

    (1~leq~W~leq~2000000)

    修改不超过 (1.6e5)

    查询不超过 (1e4)

    保证答案在整形范围内

    Solution

    这不傻逼题,直接树状数组套treap完事了

    我们考虑离线乱搞一下

    将查询改为每次查询二维前缀和容斥的形式进行四次单点查询。

    我们考虑对 (x,y) 的前缀和查询:

    我们只需要考虑修改时间在该次查询之前,且 (x_0~leq~x~land~y_0~leq~y) 的修改操作 ((x_0,y_0))

    我们发现这是一个标准的cdq分治模型:

    第一维为时间序,第二维为 (x) 坐标,第三维为 (y) 坐标。

    时间序默认有序,每次考虑前半部分的 (x_0~leq~x) 的点中 (y_0~leq~y) 的点对答案的贡献,用树状数组来统计这部分答案

    时间复杂度 (O(n~log^2 n)),空间复杂度 (O(n~log n))

    Code

    #include <cstdio>
    #include <vector>
    #include <iostream>
    #ifdef ONLINE_JUDGE
    #define freopen(a, b, c)
    #endif
    
    typedef long long int ll;
    
    namespace IPT {
    	const int L = 1000000;
    	char buf[L], *front=buf, *end=buf;
    	char GetChar() {
    		if (front == end) {
    			end = buf + fread(front = buf, 1, L, stdin);
    			if (front == end) return -1;
    		}
    		return *(front++);
    	}
    }
    
    template <typename T>
    inline void qr(T &x) {
    	char ch = IPT::GetChar(), lst = ' ';
    	while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
    	while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
    	if (lst == '-') x = -x;
    }
    
    namespace OPT {
    	char buf[120];
    }
    
    template <typename T>
    inline void qw(T x, const char aft, const bool pt) {
    	if (x < 0) {x = -x, putchar('-');}
    	int top=0;
    	do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
    	while (top) putchar(OPT::buf[top--]);
    	if (pt) putchar(aft);
    }
    
    const int maxn = 2000010;
    
    struct OP {
    	int x, y, id, v;
    
    	inline void print() {
    		std::cerr << x << ' ' << y << ' ' << id << ' ' << v << std::endl;
    	}
    };
    std::vector<OP> Q;
    
    int n, cnt;
    int ans[maxn], tree[maxn];
    
    int query(int);
    int lowbit(int);
    void cdq(int, int);
    void update(int, int);
    
    int main() {
    	freopen("1.in", "r", stdin);
    	int a, b, c, d;
    	qr(a); qr(n); a = 0; qr(a); 
    	while (a != 3) {
    		if (a == 1) {
    			a = b = c = 0; qr(a); qr(b); qr(c);
    			Q.push_back({a, b, 0, c});
    		} else {
    			a = b = c = d = 0; qr(a); qr(b); qr(c); qr(d);
    			Q.push_back({c, d, ++cnt, 1});
    			Q.push_back({a - 1, b - 1, cnt, 1});
    			Q.push_back({c, b - 1, cnt, -1});
    			Q.push_back({a - 1, d, cnt, -1});
    		}
    		a = 0; qr(a);
    	}
    	cdq(0, Q.size() - 1);
    	for (int i = 1; i <= cnt; ++i) qw(ans[i], '
    ', true);
    	return 0;
    }
    
    void cdq(int l, int r) {
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	cdq(l, mid); cdq(mid + 1, r);
    	std::vector<OP>temp;
    	int pre = l;
    	for (int i = mid + 1; i <= r; ++i) {
    		while ((pre <= mid) && (Q[pre].x <= Q[i].x)) {
    			if (Q[pre].id == 0) update(Q[pre].y, Q[pre].v);
    			temp.push_back(Q[pre++]);
    		}
    		ans[Q[i].id] += Q[i].v * query(Q[i].y);
    		temp.push_back(Q[i]);
    	}
    	for (int i = l; i < pre; ++i) if (Q[i].id == 0) update(Q[i].y, -Q[i].v);
    	while (pre <= mid) temp.push_back(Q[pre++]);
    	for (int i = l; i <= r; ++i) Q[i] = temp[i - l];
    }
    
    inline int lowbit(int x) {return x & -x;}
    
    void update(int x, int v) {
    	while (x <= n) {
    		tree[x] += v; x += lowbit(x);
    	}
    }
    
    int query(int x) {
    	int _ret = 0;
    	while (x) {
    		_ret += tree[x];
    		x -= lowbit(x);
    	}
    	return _ret;
    }
    
  • 相关阅读:
    第五章 Python——字符编码与文件处理
    第六章 Python——函数与面向过程编程
    第七章 Python——模块与包
    第一章 计算机硬件基础与操作系统介绍
    luogu P1706 全排列问题
    luogu 2142 高精度减法
    luogu P1601 高精度加法
    luogu P1803 线段覆盖 贪心
    luogu P1031 均分纸牌 贪心
    luogu P2678 跳石头 二分答案
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/10423148.html
Copyright © 2011-2022 走看看