BZOJ2877:[NOI2012]魔幻棋盘
浅谈树状数组与主席树:https://www.cnblogs.com/AKMer/p/9946944.html
题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2877
这就是个屎题。
而且至今我还不知道为什么洛谷和本地都可以过但是\(BZOJ\)会\(RE\)
利用更相减损数以棋盘守护者为中心进行二维差分,那么每次修改就变成若干个点的值的修改了。
然后二维线段树维护差分值。
详细一点你们可以看这个博客(我是懒得搞了):http://www.cnblogs.com/milky-w/p/8530723.html
反正我是不想再来回头看这题了,简直屎得一批。
2019.01.03更新:递归版代码开O3可以在BZOJ过,所以我觉得是递归的锅,果然把所有递归全部改成非递归就可以过了。还是清楚为什么递归层数并不多会RE。
时间复杂度:\(O(nmlognlogm)\)
空间复杂度:\(O(mn)\)
非递归版代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
int n,m,X,Y,T;
ll a[maxn],b[maxn];
ll read() {
ll x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
ll gcd(ll a,ll b) {
while(b) {
ll tmp=b;b=a%b;
a=tmp;
}
return abs(a);
}
struct tree_node {
int p,l,r;
tree_node () {}
tree_node (int _p,int _l,int _r) {
p=_p,l=_l,r=_r;
}
};
struct segment_tree_y {
int tot,top;
tree_node sta[maxn<<1];
int ls[maxn<<2],rs[maxn<<2];
ll val[maxn<<2],ans[maxn<<2];
int rt1[maxn<<1],rt2[maxn<<1];
void build(int root,int x) {
sta[++top]=tree_node(root,1,m);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
ls[sta[now].p]=++tot,rs[sta[now].p]=++tot;
sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(tmp.l==tmp.r)val[tmp.p]=a[(x-1)*m+tmp.l];
else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
}
}
void update(int root,int root1,int root2) {
sta[++top]=tree_node(root,1,m);
rt1[top]=root1,rt2[top]=root2;
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
ls[sta[now].p]=++tot,rs[sta[now].p]=++tot;
sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
rt1[top]=ls[rt1[now]],rt2[top]=ls[rt2[now]];
sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
rt1[top]=rs[rt1[now]],rt2[top]=rs[rt2[now]];
now++;
}
while(top) {
tree_node tmp=sta[top];
int u=rt1[top],v=rt2[top];top--;
if(tmp.l==tmp.r)val[tmp.p]=gcd(val[u],val[v]);
else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
}
}
ll query(int rt,int L,int R) {
sta[++top]=tree_node(rt,1,m);
int now=1;
while(now<=top) {
if(L<=sta[now].l&&sta[now].r<=R) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(L<=mid)sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
if(R>mid)sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(L<=tmp.l&&tmp.r<=R)ans[tmp.p]=val[tmp.p];
else {
ans[tmp.p]=0;
int mid=(tmp.l+tmp.r)>>1;
if(L<=mid)ans[tmp.p]=ans[ls[tmp.p]];
if(R>mid)ans[tmp.p]=gcd(ans[tmp.p],ans[rs[tmp.p]]);
}
}
return ans[rt];
}
void change(int p,int pos,ll v,bool opt) {
sta[++top]=tree_node(p,1,m);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(pos<=mid)sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
else sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(tmp.l==tmp.r) {
if(opt)val[tmp.p]+=v;
else val[tmp.p]=v;
}
else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
}
}
}T2;
struct segment_tree_x {
int top;
int rt[maxn<<2];
ll ans[maxn<<2];
tree_node sta[maxn<<1];
void build() {
sta[++top]=tree_node(1,1,n);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];rt[tmp.p]=++T2.tot;
if(tmp.l==tmp.r)T2.build(rt[tmp.p],tmp.l);
else T2.update(rt[tmp.p],rt[tmp.p<<1],rt[tmp.p<<1|1]);
}
}
ll query(int x1,int x2,int y1,int y2) {
sta[++top]=tree_node(1,1,n);
int now=1;
while(now<=top) {
if(x1<=sta[now].l&&sta[now].r<=x2) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(x1<=mid)sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
if(x2>mid)sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(x1<=tmp.l&&tmp.r<=x2)ans[tmp.p]=T2.query(rt[tmp.p],y1,y2);
else {
ans[tmp.p]=0;int mid=(tmp.l+tmp.r)>>1;
if(x1<=mid)ans[tmp.p]=ans[tmp.p<<1];
if(x2>mid)ans[tmp.p]=gcd(ans[tmp.p],ans[tmp.p<<1|1]);
}
}
return ans[1];
}
void add(int x,int y,ll v) {
if(x<1||x>n||y<1||y>m)return;
sta[++top]=tree_node(1,1,n);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(x<=mid)sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
else sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(tmp.l==tmp.r)T2.change(rt[tmp.p],y,v,1);
else {
ll lv=T2.query(rt[tmp.p<<1],y,y);
ll rv=T2.query(rt[tmp.p<<1|1],y,y);
T2.change(rt[tmp.p],y,gcd(lv,rv),0);
}
}
}
}T1;
int main() {
n=read(),m=read(),X=read(),Y=read(),T=read();
for(int i=1;i<=n*m;i++)a[i]=read();
for(int i=1;i<=n*m;i++) {
int pos=(i-1)%m+1;
if(pos<Y)b[i]=a[i]-a[i+1];
else if(pos>Y)b[i]=a[i]-a[i-1];
else b[i]=a[i];
}
for(int i=1;i<=n*m;i++) {
int pos=(i-1)/m+1;
if(pos<X)a[i]=b[i]-b[i+m];
else if(pos>X)a[i]=b[i]-b[i-m];
else a[i]=b[i];
}
T1.build();
while(T--) {
int opt=read(),x1=read(),y1=read(),x2=read(),y2=read();
if(!opt) {
x1=X-x1,x2=X+x2,y1=Y-y1,y2=Y+y2;
printf("%lld\n",T1.query(x1,x2,y1,y2));
}
if(opt) {
ll val=read();
if(x1<=X&&x2>=X&&y1<=Y&&y2>=Y) {
T1.add(X,Y,val);
T1.add(x1-1,y1-1,val);
T1.add(x1-1,y2+1,val);
T1.add(x2+1,y1-1,val);
T1.add(x2+1,y2+1,val);
T1.add(x1-1,Y,-val);
T1.add(x2+1,Y,-val);
T1.add(X,y1-1,-val);
T1.add(X,y2+1,-val);
}
else if(y1<=Y&&y2>=Y) {
if(x1<X) {
T1.add(x2,Y,val);
T1.add(x1-1,y1-1,val);
T1.add(x1-1,y2+1,val);
T1.add(x1-1,Y,-val);
T1.add(x2,y1-1,-val);
T1.add(x2,y2+1,-val);
}
else {
T1.add(x1,Y,val);
T1.add(x2+1,y1-1,val);
T1.add(x2+1,y2+1,val);
T1.add(x2+1,Y,-val);
T1.add(x1,y1-1,-val);
T1.add(x1,y2+1,-val);
}
}
else if(x1<=X&&x2>=X) {
if(y1<Y) {
T1.add(X,y2,val);
T1.add(x1-1,y1-1,val);
T1.add(x2+1,y1-1,val);
T1.add(X,y1-1,-val);
T1.add(x1-1,y2,-val);
T1.add(x2+1,y2,-val);
}
else {
T1.add(X,y1,val);
T1.add(x1-1,y2+1,val);
T1.add(x2+1,y2+1,val);
T1.add(X,y2+1,-val);
T1.add(x1-1,y1,-val);
T1.add(x2+1,y1,-val);
}
}
else if(x1<X&&y1<Y) {
T1.add(x2,y2,val);
T1.add(x1-1,y1-1,val);
T1.add(x1-1,y2,-val);
T1.add(x2,y1-1,-val);
}
else if(x1<X&&y1>Y) {
T1.add(x2,y1,val);
T1.add(x1-1,y2+1,val);
T1.add(x1-1,y1,-val);
T1.add(x2,y2+1,-val);
}
else if(x1>X&&y1<Y) {
T1.add(x1,y2,val);
T1.add(x2+1,y1-1,val);
T1.add(x1,y1-1,-val);
T1.add(x2+1,y2,-val);
}
else if(x1>X&&y1>Y) {
T1.add(x1,y1,val);
T1.add(x2+1,y2+1,val);
T1.add(x1,y2+1,-val);
T1.add(x2+1,y1,-val);
}
}
}
return 0;
}
递归版代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
int n,m,X,Y,T;
ll a[maxn],b[maxn];
ll read() {
ll x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
ll gcd(ll a,ll b) {
if(!b)return abs(a);
return gcd(b,a%b);
}
struct segment_tree_y {
int tot;
ll val[maxn<<2];
int ls[maxn<<2],rs[maxn<<2];
void build(int &p,int l,int r,int x) {
p=++tot;
if(l==r) {val[p]=a[(x-1)*m+l];return;}
int mid=(l+r)>>1;
build(ls[p],l,mid,x);
build(rs[p],mid+1,r,x);
val[p]=gcd(val[ls[p]],val[rs[p]]);
}
void update(int &p1,int p2,int p3,int l,int r) {
p1=++tot;
if(l==r) {val[p1]=gcd(val[p2],val[p3]);return;}
int mid=(l+r)>>1;
update(ls[p1],ls[p2],ls[p3],l,mid);
update(rs[p1],rs[p2],rs[p3],mid+1,r);
val[p1]=gcd(val[ls[p1]],val[rs[p1]]);
}
ll query(int p,int l,int r,int L,int R) {
if(L<=l&&r<=R)return val[p];
int mid=(l+r)>>1;ll res=0;
if(L<=mid)res=query(ls[p],l,mid,L,R);
if(R>mid)res=gcd(res,query(rs[p],mid+1,r,L,R));
return res;
}
void add(int p,int l,int r,int pos,ll v) {
if(l==r) {val[p]+=v;return;}
int mid=(l+r)>>1;
if(pos<=mid)add(ls[p],l,mid,pos,v);
else add(rs[p],mid+1,r,pos,v);
val[p]=gcd(val[ls[p]],val[rs[p]]);
}
void change(int p,int l,int r,int pos,ll v) {
if(l==r) {val[p]=v;return;}
int mid=(l+r)>>1;
if(pos<=mid)change(ls[p],l,mid,pos,v);
else change(rs[p],mid+1,r,pos,v);
val[p]=gcd(val[ls[p]],val[rs[p]]);
}
}T2;
struct segment_tree_x {
int rt[maxn<<2];
void build(int p,int l,int r) {
if(l==r) {T2.build(rt[p],1,m,l);return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
T2.update(rt[p],rt[p<<1],rt[p<<1|1],1,m);
}
ll query(int p,int l,int r,int x1,int x2,int y1,int y2) {
if(x1<=l&&r<=x2)return T2.query(rt[p],1,m,y1,y2);
int mid=(l+r)>>1;ll res=0;
if(x1<=mid)res=query(p<<1,l,mid,x1,x2,y1,y2);
if(x2>mid)res=gcd(res,query(p<<1|1,mid+1,r,x1,x2,y1,y2));
return res;
}
void add(int p,int l,int r,int x,int y,ll v) {
if(x<1||x>n||y<1||y>m)return;
if(l==r) {T2.add(rt[p],1,m,y,v);return;}
int mid=(l+r)>>1;
if(x<=mid)add(p<<1,l,mid,x,y,v);
else add(p<<1|1,mid+1,r,x,y,v);
ll lv=T2.query(rt[p<<1],1,m,y,y);
ll rv=T2.query(rt[p<<1|1],1,m,y,y);
T2.change(rt[p],1,m,y,gcd(lv,rv));
}
}T1;
int main() {
n=read(),m=read(),X=read(),Y=read(),T=read();
for(int i=1;i<=n*m;i++)a[i]=read();
for(int i=1;i<=n*m;i++) {
int pos=(i-1)%m+1;
if(pos<Y)b[i]=a[i]-a[i+1];
else if(pos>Y)b[i]=a[i]-a[i-1];
else b[i]=a[i];
}
for(int i=1;i<=n*m;i++) {
int pos=(i-1)/m+1;
if(pos<X)a[i]=b[i]-b[i+m];
else if(pos>X)a[i]=b[i]-b[i-m];
else a[i]=b[i];
}
T1.build(1,1,n);
while(T--) {
int opt=read(),x1=read(),y1=read(),x2=read(),y2=read();
if(!opt) {
x1=X-x1,x2=X+x2,y1=Y-y1,y2=Y+y2;
printf("%lld\n",T1.query(1,1,n,x1,x2,y1,y2));
}
if(opt) {
ll val=read();
if(x1<=X&&x2>=X&&y1<=Y&&y2>=Y) {
T1.add(1,1,n,X,Y,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,x1-1,Y,-val);
T1.add(1,1,n,x2+1,Y,-val);
T1.add(1,1,n,X,y1-1,-val);
T1.add(1,1,n,X,y2+1,-val);
}
else if(y1<=Y&&y2>=Y) {
if(x1<X) {
T1.add(1,1,n,x2,Y,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x1-1,Y,-val);
T1.add(1,1,n,x2,y1-1,-val);
T1.add(1,1,n,x2,y2+1,-val);
}
else {
T1.add(1,1,n,x1,Y,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,x2+1,Y,-val);
T1.add(1,1,n,x1,y1-1,-val);
T1.add(1,1,n,x1,y2+1,-val);
}
}
else if(x1<=X&&x2>=X) {
if(y1<Y) {
T1.add(1,1,n,X,y2,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,X,y1-1,-val);
T1.add(1,1,n,x1-1,y2,-val);
T1.add(1,1,n,x2+1,y2,-val);
}
else {
T1.add(1,1,n,X,y1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,X,y2+1,-val);
T1.add(1,1,n,x1-1,y1,-val);
T1.add(1,1,n,x2+1,y1,-val);
}
}
else if(x1<X&&y1<Y) {
T1.add(1,1,n,x2,y2,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x1-1,y2,-val);
T1.add(1,1,n,x2,y1-1,-val);
}
else if(x1<X&&y1>Y) {
T1.add(1,1,n,x2,y1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x1-1,y1,-val);
T1.add(1,1,n,x2,y2+1,-val);
}
else if(x1>X&&y1<Y) {
T1.add(1,1,n,x1,y2,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,x1,y1-1,-val);
T1.add(1,1,n,x2+1,y2,-val);
}
else if(x1>X&&y1>Y) {
T1.add(1,1,n,x1,y1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,x1,y2+1,-val);
T1.add(1,1,n,x2+1,y1,-val);
}
}
}
return 0;
}
BZOJ2877:[NOI2012]魔幻棋盘的更多相关文章
- BZOJ2877 NOI2012魔幻棋盘(二维线段树)
显然一个序列的gcd=gcd(其差分序列的gcd,序列中第一个数).于是一维情况直接线段树维护差分序列即可. 容易想到将该做法拓展到二维.于是考虑维护二维差分,查询时对差分矩阵求矩形的gcd,再对矩形 ...
- [BZOJ2877][NOI2012]魔幻棋盘(二维线段树)
https://blog.sengxian.com/solutions/bzoj-2877 注意二维线段树的upd()也是一个O(log n)的函数(pushdown()应该也是但没写过). #inc ...
- BZOJ2877 [Noi2012]魔幻棋盘
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 【bzoj2877】 Noi2012—魔幻棋盘
http://www.lydsy.com/JudgeOnline/problem.php?id=2877 (题目链接) 题意 一个${n*m}$的矩阵,维护两个操作:给任意子矩阵${+val}$:问某 ...
- 2877: [Noi2012]魔幻棋盘 - BZOJ
DescriptionInput 第一行为两个正整数N,M,表示棋盘的大小. 第二行为两个正整数X,Y,表示棋盘守护者的位置. 第三行仅有一个正整数T,表示棋盘守护者将进行次操作. 接下来N行,每行有 ...
- NOI2012 魔幻棋盘
http://www.lydsy.com/JudgeOnline/problem.php?id=2877 二维线段树. 好恶...... B类数据: 棋盘是一维的. 我们有一个结论: $gcd(a_{ ...
- 题解 洛谷 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+ ...
- 【NOI2012】魔幻棋盘
Description 将要读二年级的小 Q 买了一款新型益智玩具——魔幻棋盘,它是一个N行M列的网格棋盘,每个格子中均有一个正整数.棋盘守护者在棋盘的第X行Y列(行与列均从1开始编号) 并且始终不会 ...
随机推荐
- NativeBase准备工作
环境 node>= 4.0 npm>= 3.0 rnpm (only if React Native version < 0.29) ReactNativeCLI 安装及运行 ht ...
- erlang的undefined macro 'MODULE',头一行编译通不过的问题
前言:对于erlang的编译有很多方式,rebar,makefile文件 还是对于单个文件的erlc编译等,但不管何种方式,一个模块的第一行就编译不过去,实在让人纠结... 1)问题上述: 在技术交流 ...
- 高特权级代码段转向低特权级代码段(利用 ret(retf) 指令实现 jmp from ring0 to ring3)
[0]写在前面 0.1)本代码旨在演示 从 ring0 转移到 ring3(即,从高特权级 转移到 低特权级) 0.2)本文 只对 与 门相关的 代码进行简要注释,言简意赅: 0.3)文末的个人总结是 ...
- yum 安装apache php 使php支持memcached扩展
在公司上新项目的时候,无论生产环境还是测试环境,都会让运维安装php 环境(lamp/lnmp),并让php支持memcached 的扩展.这里搭建php环境其实主要就是搭建apache 和php.m ...
- Error -27728: Step download timeout (120 seconds)的解决方法(转)
LR中超时问题解决方法 超时错误在LoadRunner录制Web协议脚本回放时超时经常出现. 现象1:Action.c(16): Error -27728: Step download timeout ...
- HUD3689 Infinite monkey theorem
Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- COGS410. [NOI2009] 植物大战僵尸
410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:pvz.out 简单对比时间限制:2 s 内存限制:512 MB [问题描述] Plants vs ...
- Java 8 default 函数
我们知道在java8之前 ,一个类实现一个接口需要实现接口所有的方法, 但是这样会导致一个问题,当一个接口有很多的实现类的时候,修改这个接口就变成了一个非常麻烦的事,需要修改这个接口的所有实现类 不过 ...
- 单例模式(Mongo对象的创建)
单例模式: 饿汉式单例 //饿汉式单例类.在类初始化时,已经自行实例化 public class Singleton1 { //私有的默认构造子 private Singleton1() {} //已 ...
- 2017-2018-1 20179209《Linux内核原理与分析》第三周作业
一.函数调用堆栈 存储程序.函数调用堆栈(高级语言起点)和中断机制是计算机工作的三大法宝.其中函数调用堆栈是本次学习的重点.先介绍一些基本的知识点: 1.ebp 在C语言中用作记录当前函数调用的基址: ...