2877: [Noi2012]魔幻棋盘

来源:互联网 发布:明简c语言 编辑:程序博客网 时间:2024/04/28 14:07

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
原创粉丝点击