显然一个序列的gcd=gcd(其差分序列的gcd,序列中第一个数)。于是一维情况直接线段树维护差分序列即可。

  容易想到将该做法拓展到二维。于是考虑维护二维差分,查询时对差分矩阵求矩形的gcd,再对矩形的两个边界求一下原本的gcd即可。

  但这样大概需要三个二维线段树,空间可能不太够。由于查询区域是由一个给定点拓展的,可以改为以该点为中心建差分矩阵,这样剩下部分是一个十字形,可以直接一维线段树维护,就只需要一个二维线段树了。

  注意题面有锅,详见discuss,被坑了一年。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
#define ll long long
#define N 500010
#define pii pair<int,int>
#define PII pair< pii , pii >
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
ll gcd(ll n,ll m){return m==0?n:gcd(m,n%m);}
ll read()
{ll x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f;
}
int n,m,T,X,Y,root[2],cnt[2],CNT,ROOT;
ll BIT[2][N];
vector<ll> a[N];
map<PII,int> id;
struct data{int l,r,L,R;ll gcd;
}tree[2][N<<1],TREE[N*20];
void BIT_add(int op,int n,int x,ll y){while (x<=n) BIT[op][x]+=y,x+=x&-x;}
ll BIT_query(int op,int x){ll s=0;while (x) s+=BIT[op][x],x-=x&-x;return s;}
ll calc(int i,int j)
{if (i<X&&j<Y) return a[i][j]-a[i+1][j]-a[i][j+1]+a[i+1][j+1];if (i<X&&j>Y) return a[i][j]-a[i+1][j]-a[i][j-1]+a[i+1][j-1];if (i>X&&j<Y) return a[i][j]-a[i-1][j]-a[i][j+1]+a[i-1][j+1];if (i>X&&j>Y) return a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];return 0;
}
void add(int &k,int op,int l,int r,int x,ll p)
{if (!k) k=++cnt[op];if (l==r) {tree[op][k].gcd+=p;return;}int mid=l+r>>1;if (x<=mid) add(tree[op][k].l,op,l,mid,x,p);else add(tree[op][k].r,op,mid+1,r,x,p);tree[op][k].gcd=gcd(tree[op][tree[op][k].l].gcd,tree[op][tree[op][k].r].gcd);
}
ll query(int k,int op,int l,int r,int x,int y)
{if (x>y||!k) return 0; if (l==x&&r==y) return tree[op][k].gcd;int mid=l+r>>1;if (y<=mid) return query(tree[op][k].l,op,l,mid,x,y);else if (x>mid) return query(tree[op][k].r,op,mid+1,r,x,y);else return gcd(query(tree[op][k].l,op,l,mid,x,mid),query(tree[op][k].r,op,mid+1,r,mid+1,y));
}
void BUILD(int &k,int l,int r,int x)
{id[make_pair(make_pair(x,x),make_pair(l,r))]=k=++CNT;if (l==r) {TREE[k].gcd=calc(x,l);return;}int mid=l+r>>1;BUILD(TREE[k].l,l,mid,x);BUILD(TREE[k].r,mid+1,r,x);TREE[k].gcd=gcd(TREE[TREE[k].l].gcd,TREE[TREE[k].r].gcd);
}
void BUILD2(int &k,int l,int r,int u,int x,int y)
{if (!k) id[make_pair(make_pair(l,r),make_pair(x,y))]=k=++CNT;TREE[k].L=id[make_pair(make_pair(l,u),make_pair(x,y))];TREE[k].R=id[make_pair(make_pair(u+1,r),make_pair(x,y))];TREE[k].gcd=gcd(TREE[TREE[k].L].gcd,TREE[TREE[k].R].gcd);if (x==y) return;int mid=x+y>>1;BUILD2(TREE[k].l,l,r,u,x,mid);BUILD2(TREE[k].r,l,r,u,mid+1,y);
}
void update(int k,int l,int r,int x)
{TREE[k].gcd=gcd(TREE[TREE[k].L].gcd,TREE[TREE[k].R].gcd);if (l==r) return;int mid=l+r>>1;if (x<=mid) update(TREE[k].l,l,mid,x);else update(TREE[k].r,mid+1,r,x);
}
void build(int &k,int l,int r)
{if (l==r) {BUILD(k,0,m+1,l);return;}id[make_pair(make_pair(l,r),make_pair(0,m+1))]=k=++CNT;int mid=l+r>>1;build(TREE[k].L,l,mid);build(TREE[k].R,mid+1,r);BUILD2(k,l,r,(l+r>>1),0,m+1);
}
void ADD(int &k,int l,int r,int x,ll p)
{if (l==r) {TREE[k].gcd+=p;return;}int mid=l+r>>1;if (x<=mid) ADD(TREE[k].l,l,mid,x,p);else ADD(TREE[k].r,mid+1,r,x,p);TREE[k].gcd=gcd(TREE[TREE[k].l].gcd,TREE[TREE[k].r].gcd);
}
void Add(int k,int l,int r,int x,int y,ll p)
{if (l==r) {ADD(k,0,m+1,y,p);return;}int mid=l+r>>1;if (x<=mid) Add(TREE[k].L,l,mid,x,y,p);else Add(TREE[k].R,mid+1,r,x,y,p);update(k,0,m+1,y);
}
ll QUERY(int k,int l,int r,int x,int y)
{if (l==x&&r==y) return TREE[k].gcd;int mid=l+r>>1;if (y<=mid) return QUERY(TREE[k].l,l,mid,x,y);else if (x>mid) return QUERY(TREE[k].r,mid+1,r,x,y);else return gcd(QUERY(TREE[k].l,l,mid,x,mid),QUERY(TREE[k].r,mid+1,r,mid+1,y));
}
ll Query(int k,int l,int r,int xl,int xr,int yl,int yr)
{if (xl>xr||yl>yr) return 0;if (l==xl&&r==xr) return QUERY(k,0,m+1,yl,yr);int mid=l+r>>1;if (xr<=mid) return Query(TREE[k].L,l,mid,xl,xr,yl,yr);else if (xl>mid) return Query(TREE[k].R,mid+1,r,xl,xr,yl,yr);else return gcd(Query(TREE[k].L,l,mid,xl,mid,yl,yr),Query(TREE[k].R,mid+1,r,mid+1,xr,yl,yr));
}
signed main()
{
#ifndef ONLINE_JUDGEfreopen("bzoj2877.in","r",stdin);freopen("bzoj2877.out","w",stdout);const char LL[]="%I64d\n";
#elseconst char LL[]="%lld\n";
#endifn=read(),m=read(),X=read(),Y=read(),T=read();for (int j=0;j<=m+1;j++) a[0].push_back(0);for (int i=1;i<=n;i++){a[i].push_back(0);for (int j=1;j<=m;j++)a[i].push_back(read());a[i].push_back(0);}for (int j=0;j<=m+1;j++) a[n+1].push_back(0);build(ROOT,0,n+1);for (int i=1;i<=n;i++)BIT_add(0,n,i,a[i][Y]-a[i-1][Y]),add(root[0],0,1,n,i,a[i][Y]-a[i-1][Y]);for (int j=1;j<=m;j++)BIT_add(1,m,j,a[X][j]-a[X][j-1]),add(root[1],1,1,m,j,a[X][j]-a[X][j-1]);while (T--){int op=read();if (op==0){int up=read(),left=read(),down=read(),right=read();ll ans=gcd(BIT_query(0,X-up),query(root[0],0,1,n,X-up+1,X+down));ans=gcd(ans,gcd(BIT_query(1,Y-left),query(root[1],1,1,m,Y-left+1,Y+right)));ans=gcd(ans,Query(1,0,n+1,X-up,X-1,Y-left,Y-1));ans=gcd(ans,Query(1,0,n+1,X-up,X-1,Y+1,Y+right));ans=gcd(ans,Query(1,0,n+1,X+1,X+down,Y-left,Y-1));ans=gcd(ans,Query(1,0,n+1,X+1,X+down,Y+1,Y+right));printf(LL,abs(ans));}else{int xl=read(),yl=read(),xr=read(),yr=read();ll c=read();if (yl<=Y&&Y<=yr){BIT_add(0,n,xl,c),add(root[0],0,1,n,xl,c);if (xr<n) BIT_add(0,n,xr+1,-c),add(root[0],0,1,n,xr+1,-c);}if (xl<=X&&X<=xr){BIT_add(1,m,yl,c),add(root[1],1,1,m,yl,c);if (yr<m) BIT_add(1,m,yr+1,-c),add(root[1],1,1,m,yr+1,-c);}if (xl<=X&&yl<=Y){if (xr<X&&yr<Y) Add(1,0,n+1,xr,yr,c);if (xr<X) Add(1,0,n+1,xr,yl-1,-c);if (yr<Y) Add(1,0,n+1,xl-1,yr,-c);Add(1,0,n+1,xl-1,yl-1,c);}if (xr>=X&&yl<=Y){if (xl>X&&yr<Y) Add(1,0,n+1,xl,yr,c);if (xl>X) Add(1,0,n+1,xl,yl-1,-c);if (yr<Y) Add(1,0,n+1,xr+1,yr,-c);Add(1,0,n+1,xr+1,yl-1,c);}if (xl<=X&&yr>=Y){if (xr<X&&yl>Y) Add(1,0,n+1,xr,yl,c);if (xr<X) Add(1,0,n+1,xr,yr+1,-c);if (yl>Y) Add(1,0,n+1,xl-1,yl,-c);Add(1,0,n+1,xl-1,yr+1,c);}if (xr>=X&&yr>=Y){if (xl>X&&yl>Y) Add(1,0,n+1,xl,yl,c);if (xl>X) Add(1,0,n+1,xl,yr+1,-c);if (yl>Y) Add(1,0,n+1,xr+1,yl,-c);Add(1,0,n+1,xr+1,yr+1,c);}}}return 0;
}

  

转载于:https://www.cnblogs.com/Gloid/p/10325550.html

BZOJ2877 NOI2012魔幻棋盘(二维线段树)相关推荐

  1. 10.25T2 二维线段树

    Description 为了准备校庆庆典,学校招募了一些学生组成了一个方阵,准备在庆典上演出. 这个方阵是一个n*m的矩形,第i行第j列有一名学生,他有一个能力值Ai,j. 校长会定期检查一个p*q的 ...

  2. POJ2155二维线段树

    题意:      给一个n*n的01矩阵,然后有两种操作(m次)C x1 y1 x2 y2是把这个小矩形内所有数字异或一遍,Q x y 是询问当前这个点的值是多少?n<=1000 m<=5 ...

  3. poj1195 Mobile phones 二维线段树入门

    二维线段树就是树套树,线段树套线段树... #include<iostream> #include<cstdio> #include<cstring> #inclu ...

  4. POJ-2155 Matrix 二维线段树 | 树状数组

    题目链接:http://poj.org/problem?id=2155 比较典型的二维线段树题目,直接永久更新即可,在询问的时候,要询问每个x区间的子树,复杂度O(log(n)^2). 也可以用树状数 ...

  5. [POJ2155] Matrix(二维线段树,树套树)

    题目链接:http://poj.org/problem?id=2155 题意:给一个01矩阵,两个操作,翻转:子矩阵里每一个数都由0变1,1变0. 查询:查询某一点是0还是1. 一直以为二维线段树就是 ...

  6. HDU1823(二维线段树)

    题目:Luck and Love 题意:当操作符为'I'时,表示有一个MM报名,后面接着一个整数,H表示身高,两个浮点数,A表示活泼度,L表示缘分值. (100<=H<=200, 0.0& ...

  7. 【NOI2019】弹跳【二维线段树】【dijkstra】

    题意:一个w×hw\times hw×h的二维平面上有nnn个城市,有mmm个弹跳装置,第iii个可以花费tit_iti​的时间从城市pip_ipi​跳到矩形x∈[l,r],y∈[u,d]x\in [ ...

  8. 模板:二维线段树(线段树套线段树)

    文章目录 问题 解析 单点修改 询问 完整代码 标记永久化 代码 所谓二维线段树,就是有两个维度的线段树 (逃) 问题 给出一个矩形 要求支持以下操作: 1.询问一个子矩形的最值 2.修改某一个单点的 ...

  9. BZOJ.4553.[HEOI2016TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j)if(a[j ...

最新文章

  1. 编程成长日记——有意思的编程题(二)
  2. java web 心跳机制实现,基于javax的websocket服务端实现,含心跳机制
  3. 循序渐进 OSPF的详细剖析(三)
  4. css表格文字超数量就竖排_绝了,超轻量级中文 OCR,你值得拥有
  5. python限定方法参数类型、返回值类型、变量类型
  6. J2ME手游开发日记
  7. 【Redis】有序集合的交集与并集
  8. SpringBoot整合Redis(单机/哨兵/集群)
  9. GNOME如何使用Git
  10. 【待续】C#.Net 关键词清理 Fields Property Attribute Const三者之间的区别与联系
  11. [hihocoder][Offer收割]编程练习赛46
  12. 解决虚拟机中kylin连不上网络的问题
  13. JAVA抽象类和接口类的区别
  14. 计算机组成原理华中科技大学秦磊华,计算机组成原理(华科)chap1
  15. (十:2020.08.28)CVPR 2018 追踪之论文纲要(译)
  16. js从服务器获取word文档,JavaScript-js如何获取word文档页数
  17. A_A03_005 STM32程序J-LINK下载
  18. Maven之jar包冲突引入非第三方jar
  19. 完成GitHub上squirrel 的运行(数据库的模糊测试)
  20. 【Linux 0.11】第六章 引导启动程序

热门文章

  1. php数组转xml文件,php数组转换成xml格式的实现方法
  2. 【PAT (Advanced Level) Practice】1124 Raffle for Weibo Followers (20 分)
  3. python【数据结构与算法】A - How Many Tables
  4. oracle SQL 命令行(一.基础)
  5. python极简主义_XData: 为 Python 之禅写的极简主义数据验证工具
  6. 构造函数未定义_构造函数(constructor)和观察者模式,谁略胜一筹呢?
  7. html5 内嵌网页_HTML5与CSS3基础语法自学教程(二)
  8. 简单linux蠕虫,清除Linux系统上的蠕虫程序Ramen
  9. java版扫雷下载_Java 实现扫雷游戏(MineSweeper)
  10. c语言的适当大小的子集,编译原理上机实验报告