bzoj2877 [Noi2012]魔幻棋盘 [二维线段树]

http://www.lydsy.com/JudgeOnline/problem.php?id=2877题解人生苦短。#include #define p(i, j) (((i) - 1) * m + (j))#define g(i, j) (((i) - 1) * ((m << 2) + 100) + (j))#define MAXN 555555#define lch
摘要由CSDN通过智能技术生成

http://www.lydsy.com/JudgeOnline/problem.php?id=2877

题解

人生苦短。

#include <bits/stdc++.h>

#define p(i, j) (((i) - 1) * m + (j))
#define g(i, j) (((i) - 1) * ((m << 2) + 100) + (j))
#define MAXN 555555
#define lch rt << 1
#define rch rt << 1 | 1
#define lson l, mid, lch
#define rson mid + 1, r, rch

using namespace std;

int n, m, sx, sy, q;
long long d[MAXN << 2], a[MAXN << 2], ss[MAXN << 4], d1[MAXN], d2[MAXN];
long long s[2][MAXN << 2];

long long gcd(long long a, long long b) {
	if (a<0) a=-a; if (b<0) b=-b; long long temp;
    while (b) {temp=b; b=a%b; a=temp;}
    return a;
}

void update(int k, int l, int r, int rt, int x, long long c) {
	if (l == r) {
		s[k][rt] = c;
		return;
	}
	int mid = l + r >> 1;
	if (x <= mid) update(k, lson, x, c);
	else update(k, rson, x, c);
	s[k][rt] = gcd(s[k][rt << 1], s[k][rt << 1 | 1]);
}

void upy(int rx, int f, int ry, int l, int r, int y, long long c) {
	if (l == r) {
		if (f) ss[g(rx, ry)] = c;
		else ss[g(rx, ry)] = gcd(ss[g(rx << 1, ry)], ss[g(rx << 1 | 1, ry)]);
		return;
	}
	int mid = l + r >> 1;
	if (y <= mid) upy(rx, f, ry << 1, l, mid, y, c);
	else upy(rx, f, ry << 1 | 1, mid + 1, r, y, c);
	ss[g(rx, ry)] = gcd(ss[g(rx, ry << 1)], ss[g(rx, ry << 1 | 1)]);
}

void upx(int l, int r, int rt, int x, int y, long long c) {
	if (l == r) {
		upy(rt, 1, 1, 1, m, y, c);
		return;
	}
	int mid = l + r >> 1;
	if (x <= mid) upx(lson, x, y, c);
	else upx(rson, x, y, c);
	upy(rt, 0, 1, 1, m, y, c);
}

long long query(int k, int l, int r, int rt, int L, int R) {
	if (L > R) return 0;
	if (L <= l && r <= R) return s[k][rt];
	int mid = l + r >> 1;
	long long t1 = 0, t2 = 0;
	if (L <= mid) t1 = query(k, lson, L, R);
	if (R > mid) t2 = query(k, rson, L, R);
	return gcd(t1, t2);
}

long long quy(int rx, int ry, int L, int R, int l, int r) {
	if (l <= L && R <= r) return ss[g(rx, ry)];
	int mid = L + R >> 1;
	long long t1 = 0, t2 = 0;
	if (l <= mid) t1 = quy(rx, ry << 1, L, mid, l, r);
	if (r > mid) t2 = quy(rx, ry << 1 | 1, mid + 1, R, l, r);
	return gcd(t1, t2);
}

long long qux(int rx, int L, int R, int l1, int r1, int l2, int r2) {
	if (l1 > r1 || l2 > r2) return 0;
	if (l1 <= L && r1 >= R) return quy(rx, 1, 1, m, l2, r2);
	int mid = L + R >> 1;
	long long t1 = 0, t2 = 0;
	if (l1 <= mid) t1 = qux(rx << 1, L, mid, l1, r1, l2, r2);
	if (r1 > mid) t2 = qux(rx << 1 | 1, mid + 1, R, l1, r1, l2, r2);
	return gcd(t1, t2);
}

int main() {
	scanf("%d %d", &n, &m);
	scanf("%d %d", &sx, &sy);
	scanf("%d", &q);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%lld", &d[p(i, j)]);
	for (int i = 1; i < n; i++) {
		for (int j = 1; j < m; j++) {
			a[p(i, j)] = d[p(i, j)] + d[p(i + 1, j + 1)] - d[p(i + 1, j)] - d[p(i, j + 1)];
			upx(1, n, 1, i, j, a[p(i, j)]);
		}
	}
	for (int i = 1; i < n; i++) {
		d1[i] = d[p(i + 1, sy)] - d[p(i, sy)];
		update(1, 1, n, 1, i, d1[i]);
	}
	for (int i = 1; i < m; i++) {
		d2[i] = d[p(sx, i + 1)] - d[p(sx, i)];
		update(0, 1, m, 1, i, d2[i]);
	}
	int op, x1, y1, x2, y2;
	long long c;
	while (q--) {
		scanf("%d %d %d %d %d", &op, &x1, &y1, &x2, &y2);
		if (!op) {
			long long ans = gcd(d[p(sx, sy)], qux(1, 1, n, sx - x1, sx + x2 - 1, sy - y1, sy + y2 - 1));
			ans = gcd(ans, query(1, 1, n, 1, sx - x1, sx + x2 - 1));
			ans = gcd(ans, query(0, 1, m, 1, sy - y1, sy + y2 - 1));
			printf("%lld\n", ans);
		} else {
			scanf("%lld", &c);
			if (x1 != 1 && y1 != 1) upx(1, n, 1, x1 - 1, y1 - 1, a[p(x1 - 1, y1 - 1)] += c);
			if (x1 != 1 && y2 != m) upx(1, n, 1, x1 - 1, y2 , a[p(x1 - 1, y2)] -= c);
                if (x2 != n && y1 != 1) upx(1, n, 1, x2, y1 - 1, a[p(x2, y1 - 1)] -= c);
            if (x2 != n && y2 != m) upx(1, n, 1, x2, y2, a[p(x2, y2)] += c);
            if (y1 <= sy && y2 >= sy){
                if (x1 != 1) update(1, 1, n, 1, x1 - 1, d1[x1 - 1] += c);
                if (x2 != n) update(1, 1, n, 1, x2, d1[x2] -= c);
            }
            if (x1 <= sx && x2 >= sx){
                if (y1 != 1) update(0, 1, m, 1, y1 - 1, d2[y1 - 1] += c);
                if (y2 != m) update(0, 1, m, 1, y2, d2[y2] -= c);
            }
            if (x1 <= sx && x2 >= sx && y1 <= sy && y2 >= sy)
                d[p(sx, sy)] += c;
		}
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值