HDU 5454 Excited Database 线段树的维护

传送门:HDU5454

Excited Database

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 129    Accepted Submission(s): 26


Problem Description
She says that any Pavarotti among the nightingales will serenade his mate while she sits on her eggs.
She says that any excited database can answer the queries efficiently.

You are given the two dimensional database as a matrix A with n rows and n columns. In the beginning, A[i][j]=0 for all 1i,jn.
Then q operations or queries will be given in turn.

You should maintain the database for two type of operations:
1 L R: for each element A[i][j] which satisfy Li+jR, increase the value to A[i][j]+1, where 2LR2n.
2 L R: for each element A[i][j] which satisfy LijR, increase the value to A[i][j]+1, where 1nLRn1.
Meanwhile, you should answer the queries:
3 x1 x2 y1 y2: count the value of elements A[i][j] which satisfy x1ix2 and y1jy2, where 1x1<x2n and 1y1<y2n.
 


Input
The input contains several test cases. The first line of the input is a single integer t which is the number of test cases. Then t test cases follow.

Each test case contains several lines. The first line contains the integer n and q.
The i-th line of the next q lines contains an operation 1 L R" or 2 L R", or a query 3 x1 x2 y1 y2".

The sum of n for all test cases would not be larger than 200000 and the sum of q would not be larger than 50000.
 


Output
For each test case, you should output answers to queries printed one per line.
 


Sample Input
 
   
2 6 6 2 0 1 3 1 4 3 5 3 2 5 2 3 1 5 7 3 1 4 3 5 3 2 5 2 3 6 26 2 -4 -1 3 1 4 2 5 3 3 6 4 6 1 4 7 3 2 5 2 3 3 1 4 2 5 2 -3 -1 3 1 4 3 5 1 3 5 1 2 3 3 2 5 2 3 3 1 4 2 5 3 3 6 4 6 2 0 4 3 1 4 3 5 3 1 4 2 5 1 9 11 2 1 2 3 2 5 2 3 3 3 6 4 6 2 -2 2 1 7 12 3 1 4 3 5 3 2 5 2 3 3 1 4 2 5 3 3 6 4 6
 


Sample Output
 
   
Case #1: 3 4 11 10 Case #2: 10 6 8 22 26 12 38 13 32 44 23 30 49 33 67 53
 


Source
2015 ACM/ICPC Asia Regional Shenyang Online

题意:在一个n*n的矩阵中,(n<=20w),有两种操作:操作1:将A[i]j](L<= i + j <=R)  +1,操作2:将A[i][j](L<=i - j < =R )   +1. 询问x1,y1到x2,y2区域内的和。
思路:按照主对角线和副对角线分别建立线段树,操作就是区间累加操作,维护需要维护区间的sum和A[i]*i的和,查询是将矩形分解为2个等腰直角三角形和一个平行四边形。分别进行询问。
代码:
#include
#include
#include
using namespace std;
typedef __int64 LL;
const int maxn = 300005;
struct tree
{
	LL suml[maxn << 2], sumr[maxn << 2], sum[maxn << 2];
	LL add[maxn << 2];
	inline void pushup(int id, int L, int R)
	{
		LL mid = L + R >> 1;
		sum[id] = sum[id << 1] + sum[id << 1 | 1];
		suml[id] = suml[id << 1] + (mid - L + 1)*sum[id << 1 | 1] + suml[id << 1 | 1];
		sumr[id] = sumr[id << 1 | 1] + sumr[id << 1] + (R - mid)*sum[id << 1];
	}
	inline void pushdown(int id, int L, int R)
	{
		int mid = L + R >> 1;
		if (add[id])
		{
			LL ln = mid - L + 1;
			LL rn = R - mid;

			add[id << 1] += add[id];
			add[id << 1 | 1] += add[id];

			sum[id << 1] += add[id] * ln;
			sum[id << 1 | 1] += add[id] * rn;

			suml[id << 1] += add[id] * (1 + ln)*ln >> 1;
			suml[id << 1 | 1] += add[id] * (1 + rn)*rn >> 1;

			sumr[id << 1] += add[id] * (1 + ln)*ln >> 1;
			sumr[id << 1 | 1] += add[id] * (1 + rn)*rn >> 1;

			add[id] = 0;
		}
	}
	void build()
	{
		memset(sum, 0, sizeof(sum));
		memset(suml, 0, sizeof(suml));
		memset(sumr, 0, sizeof(sumr));
		memset(add, 0, sizeof(add));
	}
	LL queL(int id, int L, int R, int l, int r)
	{
		//  if(id>400000) while(1);
		if (l <= L&&R <= r) return (L - l)*sum[id] + suml[id];
		else
		{
			pushdown(id, L, R);
			int mid = L + R >> 1;
			LL res = 0;
			if (l <= mid) res += queL(id << 1, L, mid, l, r);
			if (mid> 1;
			LL res = 0;
			if (l <= mid) res += queR(id << 1, L, mid, l, r);
			if (mid> 1;
			LL res = 0;
			if (l <= mid) res += que(id << 1, L, mid, l, r);
			if (mid> 1;
			sumr[id] += (1 + sn)*sn >> 1;
		}
		else
		{
			pushdown(id, L, R);
			int mid = L + R >> 1;
			if (l <= mid) op(id << 1, L, mid, l, r);
			if (mid= max(A, C) + 1) ans += tz.queR(1, 1, n << 1, max(A, C) + 1, D);
				if (B <= min(A, C) - 1) ans += tz.queL(1, 1, n << 1, B, min(A, C) - 1);
				ans += tz.que(1, 1, n << 1, min(A, C), max(A, C))*(min(y2 - y1, x2 - x1) + 1);

				A = x1 + y1;
				B = x1 + y2;
				C = x2 + y2;
				D = x2 + y1;

				if (A <= min(B, D) - 1) ans += tf.queL(1, 1, n << 1, A, min(B, D) - 1);
				if (C >= max(B, D) + 1) ans += tf.queR(1, 1, n << 1, max(B, D) + 1, C);
				ans += tf.que(1, 1, n << 1, min(B, D), max(B, D))*(min(y2 - y1, x2 - x1) + 1);

				printf("%I64d\n", ans);
			}
		}
	}
	return 0;
}




你可能感兴趣的:(数据结构,acm,c++,数据结构,模拟)