NOI2012 魔幻棋盘
http://www.lydsy.com/JudgeOnline/problem.php?id=2877
二维线段树。
好恶。。。。。。
B类数据:
棋盘是一维的。
我们有一个结论:
$gcd(a_{1},a_{2},...,a_{n-1},a_{n})=gcd(a_{2}-a_{1},a_{3}-a_{2},...,a_{n}-a_{n-1},a_{1})$
证明:
假设集合A是a1,a2,...,an-1,an的所有公约数的集合,集合B是a2-a1,a3-a2,...,an-an-1,a1的所有公约数的集合。
对于所有的r∈A,r|a1,r|a2,...,r|an-1,r|an。
其必满足r|a2-a1,r|a3-a2,...,r|an-an-1,r|a1。
所以A⊆B。
对于所有的r∈B,r|a1,r|a2-a1,r|a3-a2,...,r|an-an-1。
其必满足:
∵r|a1,r|a2-a1
∴r|{a1-(a2-a1)} ==> r|-a2 ==> r|a2
∵r|a2,r|a3-a2
∴r|{a2-(a3-a2)} ==> r|-a3 ==> r|a3
......
∵r|an-1,r|an-an-1
∴r|{an-1 - (an - an-1)} ==> r|-an ==> r|an
所以B⊆A。
故A=B。
所以:
$gcd(a_{1},a_{2},...,a_{n-1},a_{n})=gcd(a_{2}-a_{1},a_{3}-a_{2},...,a_{n}-a_{n-1},a_{1})$
我们记b[i]=a[i]-a[i-1]。
假设询问[l,R]中的最大公约数,其实就是求gcd(a[L],gcd(b[L+1]...b[R]))。
如果将[l,R]中数都加上C,其实就是a[L...R]加上C,b[L]加上C,b[R+1]减去C。
这可以用2棵线段树维护。
C类数据:
棋盘是二维的。
我们可以从一维推广一下。
原本是这样的:
$a_{4,1},a_{4,2},a_{4,3},a_{4,4}$
$a_{3,1},a_{3,2},a_{3,3},a_{3,4}$
$a_{2,1},a_{2,2},a_{2,3},a_{2,4}$
$a_{1,1},a_{1,2},a_{1,3},a_{1,4}$
右减左:
$a_{4,1},a_{4,2}-a_{4,1},a_{4,3}-a_{4,2},a_{4,4}-a_{4,3}$
$a_{3,1},a_{3,2}-a_{3,1},a_{3,3}-a_{3,2},a_{3,4}-a_{3,3}$
$a_{2,1},a_{2,2}-a_{2,1},a_{2,3}-a_{2,2},a_{2,4}-a_{2,3}$
$a_{1,1},a_{1,2}-a_{1,1},a_{1,3}-a_{1,2},a_{1,4}-a_{1,3}$
上减下:
$a_{4,1}-a_{3,1},a_{4,2}-a_{4,1}-a_{3,2}+a_{3,1},a_{4,3}-a_{4,2}-a_{3,3}+a_{3,2},a_{4,4}-a_{4,3}-a_{3,4}+a_{3,3}$
$a_{3,1}-a_{2,1},a_{3,2}-a_{3,1}-a_{2,2}+a_{2,1},a_{3,3}-a_{3,2}-a_{2,3}+a_{2,2},a_{3,4}-a_{3,3}-a_{2,4}+a_{2,3}$
$a_{2,1}-a_{1,1},a_{2,2}-a_{2,1}-a_{1,2}+a_{1,1},a_{2,3}-a_{2,2}-a_{1,3}+a_{1,2},a_{2,4}-a_{2,3}-a_{1,4}+a_{1,3}$
$a_{1,1} , a_{1,2}-a_{1,1}, a_{1,3}-a_{1,2}, a_{1,4}-a_{1,3}$
其实就是变成了b[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]
我们在原图中以(X,Y)为原点建立平面直角坐标系,将棋盘分成四部分,每个部分的操作时一样的。
1:
以(x1,y1)为左下角,(x2,y2)为右上角的矩形区域都加C。
我们发现只有(x1,y1),(x1,y2+1),(x2+1,y1),(x2+1,y2+1)发生了改变。

单点修改,可以用二维线段树。
注意在第一维线段树中,对于非叶子节点,我们更新的时候要要从子节点中得到更新。
2:
求以(1,1)为左下角,(x,y)为右上角的矩形区间的gcd。
直接在二维线段树中询问。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=; int N,M,X,Y,T;
vector<LL> mp[maxN+]; inline LL gcd(LL a,LL b){LL ta,tb;if(a<) a=-a;if(b<) b=-b;for(;b!=;ta=b,tb=a%b,a=ta,b=tb);return a;} struct Tnode
{
Tnode *l,*r;LL v;
inline Tnode(){l=r=;v=;}
inline LL lv(){return l?l->v:;}
inline LL rv(){return r?r->v:;}
};
Tnode mem[];
int MID=-;
inline Tnode *New_Node(){mem[++MID]=Tnode();return mem+MID;} struct Tdata
{ int N,M;
Tnode *root[*maxN+];
inline void clear(int _N,int _M){N=_N;M=_M;} inline void update1(Tnode *&rt,int l,int r,int x,LL C)
{
if(l>r || x<l || r<x) return;
if(!rt) rt=New_Node();
if(x<=l && r<=x){rt->v+=C;return;}
int mid=(l+r)/;
if(x<=mid) update1(rt->l,l,mid,x,C); else update1(rt->r,mid+,r,x,C);
rt->v=gcd(rt->lv(),rt->rv());
}
inline void update2(Tnode *&rt,Tnode *&rtl,Tnode *&rtr,int l,int r,int x)
{
if(l>r || x<l || r<x) return;
if(!rt) rt=New_Node();
if(!rtl) rtl=New_Node();
if(!rtr) rtr=New_Node();
if(x<=l && r<=x){rt->v=gcd( rtl->v ,rtr->v ); return;}
int mid=(l+r)/;
if(x<=mid)update2(rt->l,rtl->l,rtr->l,l,mid,x);else update2(rt->r,rtl->r,rtr->r,mid+,r,x);
rt->v=gcd(rt->lv(),rt->rv());
}
inline LL ask(Tnode *&rt,int l,int r,int x,int y)
{
if(l>r || x>y || r<x || y<l) return ;
if(!rt) return ;
if(x<=l && r<=y) return rt->v;
int mid=(l+r)/;
return gcd( ask(rt->l,l,mid,x,y) , ask(rt->r,mid+,r,x,y) );
} inline LL ask(int rt,int l,int r,int x1,int y1,int x2,int y2)
{
if(l>r || x1>x2 || x2<l || r<x1) return ;
if(x1<=l && r<=x2) return ask(root[rt],,M,y1,y2);
int mid=(l+r)/;
return gcd( ask(rt*,l,mid,x1,y1,x2,y2) , ask(rt*+,mid+,r,x1,y1,x2,y2) );
}
inline void update(int rt,int l,int r,int x,int y,LL C)
{
if(l>r || x<l || r<x)return;
int mid=(l+r)/;
if(l==r)
update1(root[rt],,M,y,C);
else
{
if(x<=mid)update(rt*,l,mid,x,y,C); else update(rt*+,mid+,r,x,y,C);
update2(root[rt],root[rt*],root[rt*+],,M,y);
}
} inline LL xunwen(int x,int y)
{
return ask(,,N,,,x,y);
}
inline void xiugai(PII t1,PII t2,LL C)
{
int x1=t1.fi,y1=t1.se,x2=t2.fi,y2=t2.se;
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
update(,,N,x1,y1,C);
if(x2+<=N)update(,,N,x2+,y1,-C);
if(y2+<=M)update(,,N,x1,y2+,-C);
if(x2+<=N && y2+<=M)update(,,N,x2+,y2+,C);
}
}data[]; inline PII zhuan(int f,int i,int j)
{
switch(f)
{
case :return PII(j-Y+,X-i+);break;
case :return PII(Y-j+,X-i+);break;
case :return PII(Y-j+,i-X+);break;
case :return PII(j-Y+,i-X+);break;
}
} inline void build()
{
int i,j;
data[].clear(M-Y+,X);
re(i,,X)re(j,Y,M)data[].xiugai(zhuan(,i,j),zhuan(,i,j),mp[i][j]);
data[].clear(Y,X);
re(i,,X)re(j,,Y)data[].xiugai(zhuan(,i,j),zhuan(,i,j),mp[i][j]);
data[].clear(Y,N-X+);
re(i,X,N)re(j,,Y)data[].xiugai(zhuan(,i,j),zhuan(,i,j),mp[i][j]);
data[].clear(M-Y+,N-X+);
re(i,X,N)re(j,Y,M)data[].xiugai(zhuan(,i,j),zhuan(,i,j),mp[i][j]);
} int main()
{
freopen("chess.in","r",stdin);
freopen("chess.out","w",stdout);
int i,j;
N=gint();M=gint();
X=gint();Y=gint();
T=gint();
re(i,,N){mp[i].push_back();re(j,,M)mp[i].push_back(gll());mp[i].push_back();}
re(j,,M+)mp[].push_back(),mp[N+].push_back();
build();
while(T--)
{
int f=gint(),x1=gint(),y1=gint(),x2=gint(),y2=gint();
LL C,res;
switch(f)
{
case :
res=;
res=gcd(res,data[].xunwen(y2+,x1+));
res=gcd(res,data[].xunwen(y1+,x1+));
res=gcd(res,data[].xunwen(y1+,x2+));
res=gcd(res,data[].xunwen(y2+,x2+));
PF("%I64d\n",res);
break;
case :
C=gll();
if(x1<=X && y2>=Y) data[].xiugai( zhuan(,min(X,x2),max(Y,y1)) , zhuan(,x1,y2) , C );
if(x1<=X && y1<=Y) data[].xiugai( zhuan(,min(X,x2),min(Y,y2)) , zhuan(,x1,y1) , C );
if(x2>=X && y1<=Y) data[].xiugai( zhuan(,max(X,x1),min(Y,y2)) , zhuan(,x2,y1) , C );
if(x2>=X && y2>=Y) data[].xiugai( zhuan(,max(X,x1),max(Y,y1)) , zhuan(,x2,y2) , C );
break;
}
}
return ;
}
NOI2012 魔幻棋盘的更多相关文章
- 2877: [Noi2012]魔幻棋盘 - BZOJ
DescriptionInput 第一行为两个正整数N,M,表示棋盘的大小. 第二行为两个正整数X,Y,表示棋盘守护者的位置. 第三行仅有一个正整数T,表示棋盘守护者将进行次操作. 接下来N行,每行有 ...
- BZOJ2877 [Noi2012]魔幻棋盘
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- BZOJ2877:[NOI2012]魔幻棋盘
浅谈树状数组与主席树:https://www.cnblogs.com/AKMer/p/9946944.html 题目传送门:https://lydsy.com/JudgeOnline/problem. ...
- 题解 洛谷 P2086 【[NOI2012]魔幻棋盘】
先考虑只有一维的情况,要求支持区间加和求区间 \(\gcd\),根据 \(\gcd\) 的性质,发现: \[ \gcd(a_1,a_2,a_3,\ldots a_n)=\gcd(a_i,a_2-a_1 ...
- 数据结构(二维线段树,差分): NOI2012 魔幻棋盘
貌似想复杂了…… #include <iostream> #include <cstring> #include <cstdio> #define mid ((l+ ...
- BZOJ2877 NOI2012魔幻棋盘(二维线段树)
显然一个序列的gcd=gcd(其差分序列的gcd,序列中第一个数).于是一维情况直接线段树维护差分序列即可. 容易想到将该做法拓展到二维.于是考虑维护二维差分,查询时对差分矩阵求矩形的gcd,再对矩形 ...
- [BZOJ2877][NOI2012]魔幻棋盘(二维线段树)
https://blog.sengxian.com/solutions/bzoj-2877 注意二维线段树的upd()也是一个O(log n)的函数(pushdown()应该也是但没写过). #inc ...
- 【bzoj2877】 Noi2012—魔幻棋盘
http://www.lydsy.com/JudgeOnline/problem.php?id=2877 (题目链接) 题意 一个${n*m}$的矩阵,维护两个操作:给任意子矩阵${+val}$:问某 ...
- 【NOI2012】魔幻棋盘
Description 将要读二年级的小 Q 买了一款新型益智玩具——魔幻棋盘,它是一个N行M列的网格棋盘,每个格子中均有一个正整数.棋盘守护者在棋盘的第X行Y列(行与列均从1开始编号) 并且始终不会 ...
随机推荐
- windows 自动安装
msiexec
- css和js引用图片的路径问题
原文转自:http://www.cnblogs.com/azumia/archive/2012/06/17/2552346.html 在JS文件中书写相对路径:JS文件是指在页面中引用的外部JavaS ...
- 贪心-poj-3040-Allowance
题目链接: http://poj.org/problem?id=3040 题目意思: 有n种(n<=20)面额的硬币,每种硬币面值能整除比它大的面值.给一个c,告诉每种硬币的面值和数量,求最多能 ...
- HDOJ1251-统计难题(trie树入门)
统计难题 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others) Total Subm ...
- centos7启动时出现“无法应用原保存的显示器配置”
设置了分辨率后,登录提示“出现无法应用原保存的显示器配置”. 解决办法: 打开终端,输入 rm ~/.config/monitors.xml 然后重新登录, 问题解决.
- 前端笔试题目总结——应用JavaScript函数递归打印数组到HTML页面上
数组如下: var item=[{ name:'Tom', age:70, child:[{ name:'Jerry', age:50, child:[{ name:'William', age:20 ...
- MVC文件上传 - 使用Request.Files上传多个文件
控制器 1: using System; 2: using System.Collections.Generic; 3: using System.IO; 4: using System.Linq; ...
- java日期操作
//字符串转日期 public static void dt7() throws ParseException { String str_date="2015---08---08" ...
- 在同个类中non-const插入const来减少重复
class A { private: std::string a; public: A(std::string b) :a(b){} const char& operator[](int b) ...
- 状态压缩dp zoj3802
做这个题的时候看了看时间复杂度觉得应该是个贪心或者dp,然后贪心又很快被否定了,因为不具备贪心的一些特性,想了想觉得没什么思路.看了下网上的思路,真是让人拍案叫绝,算法的魅力就在于此啊.. 首先dp就 ...