BZOJ3132上帝造題的七分鐘

3132: 上帝造題的七分鐘
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 647 Solved: 294
Description
“第一分鐘,X說,要有矩陣,於是便有了一個裏面寫滿了0的n×m矩陣。
第二分鐘,L說,要能修改,於是便有了將左上角爲(a,b),右下角爲(c,d)的一個矩形區域內的全部數字加上一個值的操作。
第三分鐘,k說,要能查詢,於是便有了求給定矩形區域內的全部數字和的操作。
第四分鐘,彩虹喵說,要基於二叉樹的數據結構,於是便有了數據範圍。
第五分鐘,和雪說,要有耐心,於是便有了時間限制。
第六分鐘,喫鋼琴男說,要省點事,於是便有了保證運算過程中及最終結果均不超過32位有符號整數類型的表示範圍的限制。
第七分鐘,這道題終於造完了,然而,造題的神牛們再也不想寫這道題的程序了。”
——《上帝造裸題的七分鐘》
所以這個神聖的任務就交給你了。
Input
輸入數據的第一行爲X n m,代表矩陣大小爲n×m。
從輸入數據的第二行開始到文件尾的每一行會出現以下兩種操作:
  L a b c d delta —— 代表將(a,b),(c,d)爲頂點的矩形區域內的所有數字加上delta。
  k a b c d   —— 代表求(a,b),(c,d)爲頂點的矩形區域內所有數字的和。
請注意,k爲小寫。
Output
針對每個k操作,在單獨的一行輸出答案。
Sample Input
X 4 4
L 1 1 3 3 2
L 2 2 4 4 1
k 2 2 3 3
Sample Output
12
HINT
對於100%的數據,1 ≤ n ≤ 2048, 1 ≤ m ≤ 2048, 1 ≤ abs(delta) ≤ 500,操作不超過200000個,保證運算過程中及最終結果均不超過32位帶符號整數類型的表示範圍。
Source
tyvj
二維樹狀數組+2D逆求和數組
一開始以爲是水題。。
於是秒打了個二維樹狀數組上去,結果T了。。。
然後發現操作數極多。。
沒有想到任何可以優化的方法。。
然後看到zkw的神思路是2D逆求和數組。。
開四個二維樹狀數組,分別記錄行和列都沒有修改的、只修改行的、只修改列的、行和列都被修改的。。
然後就可以水了。。
附上本蒟蒻的代碼:

#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
int n,m;
struct kx
{
    int f[2050][2050];
    int lowbit(int x)
      {
         return x&(-x);
      }
    void add(int x,int y,int t)
      {
         int i,j;
         for (i=x;i<=n;i+=lowbit(i))
           for (j=y;j<=n;j+=lowbit(j))
             f[i][j]+=t;
      }
    int query(int x,int y)
      {  
         int i,j,ans=0;
         for (i=x;i>=1;i-=lowbit(i))
           for (j=y;j>=1;j-=lowbit(j))
             ans+=f[i][j];
         return ans;
      }
}a,b,c,d;

int read()
{
    int w=0,flag=1; char ch=getchar();
    while (ch<'0' || ch>'9')
      {
        if (ch=='-') flag=-1;
        ch=getchar();
      }
    while (ch>='0' && ch<='9')
      w=w*10+ch-'0',ch=getchar();
    return w*flag;
}

void insert(int x1,int y1,int x2,int y2,int delta)
{
    a.add(x1,y1,delta),a.add(x2+1,y2+1,delta),a.add(x2+1,y1,-delta),a.add(x1,y2+1,-delta);
    b.add(x1,y1,delta*x1),b.add(x2+1,y2+1,(x2+1)*delta),b.add(x2+1,y1,-delta*(x2+1)),b.add(x1,y2+1,-delta*(x1));
    c.add(x1,y1,delta*y1),c.add(x2+1,y2+1,(y2+1)*delta),c.add(x2+1,y1,-delta*y1),c.add(x1,y2+1,-delta*(y2+1));
    d.add(x1,y1,delta*x1*y1),d.add(x2+1,y2+1,(x2+1)*(y2+1)*delta),d.add(x2+1,y1,-delta*y1*(x2+1)),d.add(x1,y2+1,-delta*x1*(y2+1));
}

int querysum(int x,int y)
{
    return a.query(x,y)*(x+1)*(y+1)-b.query(x,y)*(y+1)-c.query(x,y)*(x+1)+d.query(x,y);
}

int main()
{
    int x1,y1,x2,y2,delta,i,j;
    char s[4];
    scanf("%s",&s),n=read(),m=read();
    while ((scanf("%s",&s))!=EOF)
      {
        x1=read(),y1=read(),x2=read(),y2=read();
        if (s[0]=='L') 
          {
            delta=read();
            insert(x1,y1,x2,y2,delta);
          }
        if (s[0]=='k')
          printf("%d\n",querysum(x2,y2)-querysum(x1-1,y2)-querysum(x2,y1-1)+querysum(x1-1,y1-1));
      }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章