好吧,昨晚刚刚打完cf,做了两道水题,其实第三道这道数学题不难,用逆向思维去做就好,可是我脑子转不过来~又放弃治疗,只看题意,下次要提起精神,最少想两个思路来尝试,否则熬夜打比赛就显得没必要和不值得了。
额,其实这次想说的是Tyvj上一道我wa了挺久的题目,其实还是水题,就是逻辑不严谨和思路混乱,导致代码也很乱,但是今天一爬起来,就强迫自己说服自己,一定要给出一个严谨可行的思路出来!经过好多次debug和画图分析,终于写出了好简单的codes,哈哈,忘了贴题目了:
背景 Background
Unit6 数星星提示:
1.可以使用简单的容斥原理维护前缀和
描述 Description
小z在无聊的时候总爱仰望天空,他把天空分成了N*M块,每一块都有若干个星星,他想知道第(x1,y1)到第(x2,y2)之间一共有多少颗星星呢?输入格式 InputFormat
一行两个整数n、m和p,n和m的含义同上文,p的含义是询问个数紧接着有n行,每行m个数,表示(i,j)块有的星星数目
接下来有p行,每行四个整数x1,y1,x2,y2,表示询问(x1,y1)到(x2,y2)的星星个数
输出格式 OutputFormat
一共p行,对于每一个询问输出一行,表示(x1,y1)到(x2,y2)的星星个数样例输入 SampleInput [复制数据]
3 3 1 1 2 3 4 5 6 7 8 9 1 1 3 3
样例输出 SampleOutput [复制数据]
45
数据范围和注释 Hint
对于10%的数据 n,m<=10 p<=10对于70%的数据 n,m<=100 p<=1000
对于100%的数据 n,m<=1000 p<=10000 每一块中的星星数目<=100
#include <iostream>
using namespace std;
int p[1000][1000];
int q[1000000];
void cake(int row, int col)
{
q[0] = p[0][0];
for(int i=0; i<row; ++i)
{
for(int j=0; j<col; ++j)
{
if(i==0&&j==0) continue;
q[i*row+j] = q[i*row+j-1] + p[i][j];
}
}
}
int main()
{
int row, col, h, buf;
cin >> row >> col >> h;
for(unsigned int i=0; i<row; ++i)
{
for(unsigned int j=0; j<col; ++j)
cin >> p[i][j];
}
cake(row,col);
int x1, y1, x2, y2, ans;
while(h--)
{
cin >> x1 >> y1 >> x2 >> y2;
--x1;
--y1;
--x2;
--y2;
ans = 0;
for(int i=x1; i<=x2; ++i)
ans += (q[i*row+y2]-q[i*row+y1]+p[i][y1]);
cout << ans << endl;
}
return 0;
}
其实就是题目里提示的使用容斥原理来维护前缀和,建一个q数组来存放前缀和,然后不要想一口气就怎么怎么得到ans,因为可能你要减掉的东西不存在,比如我一开始用的是ans += (q[i*row+y2]-q[i*row+y1-1]);
想清楚,不对呀,如果i=0y1=0的时候,岂不是减掉了q[-1]了?那就加一个判断吧,,,,后来越弄越复杂,算了,不要了,一切从简!就减多一个所求矩阵范围的一个元素,再加回来就好了,因为矩阵的元素一定是存在的!所以就有了:(q[i*row+y2]-q[i*row+y1]+p[i][y1]);
哈哈,泡面去!