最近北航ACM队内看是流行一款叫做RUSE的即时策略游戏,这款游戏的迷人之处就在于真真假假虚虚实实,对抗性很强。Sbihero是这方面的达人,因为他为了这个游戏构造了一个合适的模型:
将整个战场可以视为为n*m的一个矩阵,每个元素值都代表着这一区域内的战力值,正值代表己方的战力,负值代表敌方的战力,零表示无军事力量。
而Sbihero最喜欢用的国家德国还有一项特殊的战术——闪电战。闪电战必须在一个连续的区域内发动,动员这一区域内的全部己方军事力量向敌方进攻。如果此区域己方的战力总和大于敌方的战力总和,那么这场闪电战就记为胜利,否则为失败。结果即为己方战力和敌方战力的差值。
现在Sbihero算数算不过来了…他麻烦你来写一个程序,计算在已知战场上任意一连续区域内发动闪电战的结果。(每个连续区域用一个封闭的顺时针折线来围成)如下图区域:
可以表示为(6,2)-->(8,2)-->(8,8)-->(2,8)-->(2,4)-->(4,4)-->(4,6)-->(6,6)-->(6,2)
输入第一行为数据组数t(t<=20)。
对于每组数据,第一行包含两个整数X,Y(1<X,Y<=1000),表示战场大小。后面Y行,每行X个整数,表示战场上的战力分布,正数表示己方战力,负数表示敌方战力。
下面一行包含一个整数k(k<=1000),表示查询的总数。
紧跟着k行表示k组查询区域:每组查询首先是一个整数T(T<=1000),表示这个轮廓线上的折点数。后面有2*T个正整数,每两个整数,表示一个折点的坐标(保证按顺时针顺序给出)。
保证这条折线是封闭的,并且不相交(相交于点上不算,详细见样例的第2组查询)。
2 10 9 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 6 2 8 2 8 8 2 8 2 4 4 4 4 6 6 6 10 5 3 7 3 7 6 4 6 4 4 5 4 5 5 6 5 6 4 5 4 10 9 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 -2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 6 2 8 2 8 8 2 8 2 4 4 4 4 6 6 6 10 5 3 7 3 7 6 4 6 4 4 5 4 5 5 6 5 6 4 5 4
0 1 -10
计算一块联通块里的和是多少,由于给出的是点,顺序又是顺时针的,其实可以不用考虑竖线的情况,看每
一条横线,从图中可以找到,所有的横线可以对应于横线上面全部的和,向右的当做减,向左的当做加,这
样加起来就是答案了。
#include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define ms(x,y) memset(x,y,sizeof(x)) #define rep(i,j,k) for(int i=j;i<=k;i++) #define loop(i,j,k) for (int i=j;i!=-1;i=k[i]) #define inone(x) scanf("%d",&x) #define intwo(x,y) scanf("%d%d",&x,&y) #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z) #define lson x<<1,l,mid #define rson x<<1|1,mid+1,r const int N = 1e3 + 10; const int INF = 0x7FFFFFFF; int T, n, m, a[N][N]; int p, q, x[N], y[N]; long long s[N][N], res; int main() { for (inone(T); T--;) { intwo(n, m); rep(i, 1, m) rep(j, 1, n) inone(a[i][j]); rep(i, 0, n) rep(j, 0, m) { if (!i || !j) { s[i][j] = 0; continue; } s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[j][i]; } for (inone(q); q--;) { res = 0; inone(p); rep(i, 0, p - 1) intwo(x[i], y[i]); x[p] = x[0]; y[p] = y[0]; rep(i, 0, p - 1) { if (y[i] == y[i + 1]) res += s[x[i]][y[i]] - s[x[i + 1]][y[i + 1]]; } printf("%lld\n", res); } } return 0; }