数星星~

好吧,昨晚刚刚打完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
下面是我的ac代码:

#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]);

哈哈,泡面去!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值