2877: [Noi2012]魔幻棋盘

2877: [Noi2012]魔幻棋盘

Time Limit: 50 Sec   Memory Limit: 512 MB
Submit: 808   Solved: 317
[ Submit][ Status][ Discuss]

Description

Input

第一行为两个正整数N,M,表示棋盘的大小。 第二行为两个正整数X,Y,表示棋盘守护者的位置。 第三行仅有一个正整数T,表示棋盘守护者将进行次操作。 接下来N行,每行有M个正整数,用来描述初始时棋盘上每个位置的数。 接下来T行,按操作的时间顺序给出T次操作。每行描述一次操作,以一个数字0或1开头: 若以数字0开头,表示此操作为询问,随后会有四个非负整数x1,y1,x2,y2,表示询问的区域是以棋盘守护者的位置为基础向上扩展x1行,向下扩展y1行,向左扩展x2列,向右扩展y2列得到的矩形区域(详见样例)。 若以数字1开头,表示此操作为修改,随后会有四个正整数x1,y1,x2,y2和一个整数c,表示修改区域的上、下边界分别为第x1,x2行,左、右边界分别为第y1,y2列(详见样例),在此矩形区域内的所有数统一加上c(注意c可能为负数)。

Output


 对于每次询问操作,每行输出一个数,表示该区域内所有数的最大公约数。

Sample Input

2 2
1 1
4
6 12
18 24
0 0 0 1 0
1 1 1 1 2 6
1 2 1 2 2 6
0 0 0 1 1


Sample Output

6 6

HINT

Source

[ Submit][ Status][ Discuss]

还是去看noi2012原题吧  wuliwala传送门

大概就是给你一个二维棋盘然后在里面修改区间查询区间gcd,查询操作有一个固定中心
gcd(a,b) = gcd(a,a-b)--更相减损术
对于一维的操作,由上式得gcd(a1,a2,a3,...,an) = gcd(a1,a2-a1,a3-a2,...,an-an-1)
所以。。原序列gcd=原序列的差分序列的gcd
线段树维护区间gcd,修改操作只改2个点

对于二维,二维差分定义为a[i][j] = a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]
当然朝四个方向都可以
利用题目给的中心,二维线段树维护四个方向的差分,然后x行与y列特别维护指向中心的一维差分
每次修改最多8个点bulabulabulabula(写的时候N多地方出错)

查询返回值应先定义为0而不是1
涉及gcd操作应使用绝对值
需要修改的单点被多次修改!!!(额外附加判断数组)

万恶的编写错误--Modify函数调用que函数时节点o应为当前节点的左右子节点,Modify函数赋值出错,Judge函数竟然写了两个dx
而且而且。。。getLL居然没考虑负数?!!!!!



#include<iostream>      
#include<cstdio>      
#include<cstring>      
#include<cmath>    
#include<vector>      
using namespace std;      
         
const int maxn = 5E5 + 10;     
const int dx[4][4] = {{0,0,1,1},{0,0,1,1},{0,0,-1,-1},{0,0,-1,-1}};    
const int dy[4][4] = {{0,1,0,1},{0,-1,0,-1},{0,1,0,1},{0,-1,0,-1}};     
typedef long long LL;      
         
LL c[maxn*25];      
int n,m,t,x,y,X1,X2,Y1,Y2,cnt = 0,tt,lc[maxn*20],rc[maxn*20];   
int jx[10],jy[10],cur;     
         
vector <LL> v[maxn];    
vector <int> bo[maxn];
         
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}      
     
LL ABS(LL x) {return x>0?x:x*-1;}  
     
void PRE(int l,int r,int o)      
{      
    cnt = max(cnt,o);      
    if (l == r) return;      
    int mid = (l+r) >> 1;      
    PRE(l,mid,2*o); PRE(mid+1,r,2*o+1);      
}  
         
LL que(int o,int l,int r,int ql,int qr)    
{    
    if (ql <= l && r <= qr) return ABS(c[o]);    
    LL ret = 0;    
    int mid = (l+r) >> 1;    
    if (ql <= mid) ret = gcd(ret,que(lc[o],l,mid,ql,qr));    
    if (qr > mid) ret = gcd(ret,que(rc[o],mid+1,r,ql,qr));    
    return ret;    
}  
       
LL Modi(int l,int r,int o,int pos,LL va,int typ)      
{      
    if (l == r) {if (typ) c[o] = va; else c[o] += va; return ABS(c[o]);}      
    int mid = (l+r) >> 1; LL ret;  
    if (pos <= mid) {      
        if (!lc[o]) lc[o] = ++cnt;      
        ret = Modi(l,mid,lc[o],pos,va,typ);      
    }      
    else {      
        if (!rc[o]) rc[o] = ++cnt;      
        ret = Modi(mid+1,r,rc[o],pos,va,typ);      
    }      
    c[o] = gcd(ABS(c[lc[o]]),ABS(c[rc[o]]));  
    return ret;  
}      
         
LL Modify(int l,int r,int o,int pn,int pm,LL va)      
{      
    if (!pn || !pm || pn > n || pm > m) return -1;    
    if (l == r) return Modi(1,m,o,pm,va,0);      
    int mid = (l+r) >> 1;      
    LL ret1,ret2;  
    if (pn <= mid) {  
        ret1 = Modify(l,mid,2*o,pn,pm,va);  
        ret2 = que(2*o+1,1,m,pm,pm);   
    }     
    else {  
        ret1 = Modify(mid+1,r,2*o+1,pn,pm,va);  
        ret2 = que(2*o,1,m,pm,pm);      
    }  
    return Modi(1,m,o,pm,gcd(ret1,ret2),1);  
}      
         
LL getLL()    
{    
    LL ret = 0;  LL xx = 1;  
    char ch = getchar();    
    while (ch < '0' || ch > '9') {  
        if (ch == '-') xx = -1;  
        ch = getchar();   
    }  
    while ('0' <= ch && ch <= '9') ret = ret*10 + 1LL*(ch-'0'),ch = getchar();    
    return ret*xx;    
}    
         
void Judge(int px,int py,LL c)    
{    
    if (!px || !py || px > n || py > m || px == x || py == y) return;   
	if (bo[px][py] == tt) return; 
    int po;    
    if (px < x && py < y) po = 0;    
    else if (px < x && py > y) po = 1;    
    else if (px > x && py < y) po = 2;    
    else po = 3;    
    LL tot = 0;    
    for (int l = 0; l < 4; l++) {    
        int xx = px + dx[po][l];    
        int yy = py + dy[po][l];    
        LL t;    
        if ((!dx[po][l] || !dy[po][l]) && dx[po][l] != dy[po][l]) t = -1;  else t = 1;    
        if (X1 <= xx && xx <= X2 && Y1 <= yy && yy <= Y2) tot += c*t;    
    }    
    if (tot != 0) Modify(1,n,1,px,py,tot),bo[px][py] = tt,jx[cur] = px,jy[cur++] = py;    
}     
         
LL query(int o,int l,int r,int nl,int nr,int ml,int mr)    
{    
    if (nl <= l && r <= nr) return que(o,1,m,ml,mr);    
    LL ret = 0;    
    int mid = (l+r) >> 1;    
    if (nl <= mid) ret = gcd(ret,query(2*o,l,mid,nl,nr,ml,mr));    
    if (nr > mid) ret = gcd(ret,query(2*o+1,mid+1,r,nl,nr,ml,mr));    
    return ret;    
}      
       
int main()      
{      
    #ifdef YZY      
        //freopen("chess1.in","r",stdin);      
        //freopen("test.txt","w",stdout);  
    #endif      
             
    cin >> n >> m >> x >> y >> t; PRE(1,n,1);      
    for (int i = 1; i <= n; i++) {    
        v[i].push_back(0);    bo[i].push_back(0);
        for (int j = 1; j <= m; j++) {    
            LL x; x = getLL();    
            v[i].push_back(x);    bo[i].push_back(0);
        }    
    }    
           
    for (int i = 1; i <= n; i++)    
        for (int j = 1; j <= m; j++) {    
            if (i == x && j == y) Modify(1,n,1,i,j,v[i][j]);    
            else if (i == x && j < y) Modify(1,n,1,i,j,v[i][j]-v[i][j+1]);    
            else if (i == x && j > y) Modify(1,n,1,i,j,v[i][j]-v[i][j-1]);    
            else if (j == y && i < x) Modify(1,n,1,i,j,v[i][j]-v[i+1][j]);    
            else if (j == y && i > x) Modify(1,n,1,i,j,v[i][j]-v[i-1][j]);    
            else if (i < x && j < y) Modify(1,n,1,i,j,v[i][j]-v[i+1][j]-v[i][j+1]+v[i+1][j+1]);    
            else if (i < x && j > y) Modify(1,n,1,i,j,v[i][j]-v[i+1][j]-v[i][j-1]+v[i+1][j-1]);    
            else if (i > x && j < y) Modify(1,n,1,i,j,v[i][j]-v[i-1][j]-v[i][j+1]+v[i-1][j+1]);    
            else Modify(1,n,1,i,j,v[i][j]-v[i][j-1]-v[i-1][j]+v[i-1][j-1]);    
        }  
            
    while(t--) {      
        int typ = getLL();    
        if (typ == 0) {    
            X1 = getLL(); Y1 = getLL();     
            X2 = getLL(); Y2 = getLL();    
            X1 = x - X1; X2 = x + X2;    
            Y1 = y - Y1; Y2 = y + Y2;    
            printf("%lld\n",query(1,1,n,X1,X2,Y1,Y2));    
        }    
        else {    
        	++tt;
            X1 = getLL(); Y1 = getLL();     
            X2 = getLL(); Y2 = getLL();    
            LL c; c = getLL();  cur = 0;  
            Judge(X1-1,Y1-1,c); Judge(X1,Y1-1,c); Judge(X1,Y1,c); Judge(X1-1,Y1,c);    
            Judge(X1-1,Y2,c); Judge(X1-1,Y2+1,c); Judge(X1,Y2+1,c); Judge(X1,Y2,c);    
            Judge(X2,Y1,c);  Judge(X2+1,Y1,c); Judge(X2+1,Y1-1,c); Judge(X2,Y1-1,c);   
            Judge(X2,Y2,c); Judge(X2,Y2+1,c); Judge(X2+1,Y2,c); Judge(X2+1,Y2+1,c);    
            if (X1 <= x && x <= X2 && Y1 <= y && y <= Y2) Modify(1,n,1,x,y,c);    
            if (X1 <= x && x <= X2) {    
                if (Y1 <= y && y <= Y2) Modify(1,n,1,x,Y2+1,-c),Modify(1,n,1,x,Y1-1,-c);    
                else if (y > Y2) Modify(1,n,1,x,Y2,c),Modify(1,n,1,x,Y1-1,-c);    
                else Modify(1,n,1,x,Y1,c),Modify(1,n,1,x,Y2+1,-c);    
            }    
            if (Y1 <= y && y <= Y2) {    
                if (X1 <= x && x <= X2) Modify(1,n,1,X1-1,y,-c),Modify(1,n,1,X2+1,y,-c);    
                else if (x > X2) Modify(1,n,1,X2,y,c),Modify(1,n,1,X1-1,y,-c);    
                else Modify(1,n,1,X1,y,c),Modify(1,n,1,X2+1,y,-c);    
            }    
        }    
    }      
    return 0;      
}     



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值