首页 > 其他分享 >树套树做矩形加矩形求和。

树套树做矩形加矩形求和。

时间:2023-02-09 09:23:52浏览次数:47  
标签:树套 rs 求和 mid int read 区间 query 矩形

题目大意:
有一个 \(n\times n\) 的矩阵,每个位置上初始值都为 \(0\),\(q\) 次操作,分为两种:
1.把横坐标在 \([x_1,x_2]\) 范围内,纵坐标在 \([y_1,y_2]\) 范围内的所有数加上一个 \(val\);
2.求横坐标在 \([x_1,x_2]\) 范围内,纵坐标在 \([y_1,y_2]\) 范围内的所有数的值的和。
数据范围:
\(n,q\le 200000\)。

解法:

维护两棵线段树套线段树,记为A和B。

每次矩形加的时候,在A的外层上找到对应区间,对内层进行区间加,维护区间和。

在B的外层上在找到对应区间之前遍历到的所有节点,对那些节点的内层线段树区间加,维护区间和。

然后查询一个矩形和的时候,就是在B的外层对应位置上找到对应区间,区间求和。

在A的外层上在找到对应区间之前遍历到的所有节点,计算与询问区间的交的面积作为系数,区间求和。

Talk is cheap,and this is my Code.

#include <iostream>
using namespace std ;

#define int long long
const int N = 400005 , L = 20 ;
int n , q , dt , rt[N] , ls[N*L*L] , rs[N*L*L] ;

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

struct Sgt {

int t[N*L*L] , g[N*L*L] ;

void pushdown ( int k , int l , int r ) {
	if ( ! g [ k ] ) return ;
	if ( ! ls [ k ] ) ls [ k ] = ++ dt ;
	if ( ! rs [ k ] ) rs [ k ] = ++ dt ;
	int mid = ( l + r ) >> 1 ;
	t [ ls [ k ] ] += ( mid - l + 1 ) * g [ k ] ;
	t [ rs [ k ] ] += ( r - mid ) * g [ k ] ;
	g [ ls [ k ] ] += g [ k ] ;
	g [ rs [ k ] ] += g [ k ] ;
	g [ k ] = 0 ;
}

void modify ( int &k , int l , int r , int x , int y , int z ) {
	if ( ! k ) k = ++ dt ;
	if ( x <= l && r <= y ) {
		t [ k ] += z * ( r - l + 1 ) ;
		g [ k ] += z ;
		return ;
	}
	pushdown ( k , l , r ) ;
	int mid = ( l + r ) >> 1 ;
	if ( x <= mid ) modify ( ls [ k ] , l , mid , x , y , z ) ;
	if ( y > mid ) modify ( rs [ k ] , mid + 1 , r , x , y , z ) ;
	t [ k ] = t [ ls [ k ] ] + t [ rs [ k ] ] ;
}

int query ( int k , int l , int r , int x , int y ) {
	if ( x <= l && r <= y )
		return t [ k ] ;
	pushdown ( k , l , r ) ;
	int mid = ( l + r ) >> 1 ;
	if ( y <= mid ) return query ( ls [ k ] , l , mid , x , y ) ;
	if ( x > mid ) return query ( rs [ k ] , mid + 1 , r , x , y ) ;
	return query ( ls [ k ] , l , mid , x , y ) + query ( rs [ k ] , mid + 1 , r , x , y ) ;
}

} A , B ;

void change ( int k , int l , int r , int x , int y , int L , int R , int z ) {
	if ( x <= l && r <= y ) {
		A .modify ( rt [ k ] , 1 , n , L , R , z ) ;
		return ;
	}
	B .modify ( rt [ k ] , 1 , n , L , R , z * ( min ( r , y ) - max ( l , x ) + 1 ) ) ;
	int mid = ( l + r ) >> 1 ;
	if ( x <= mid ) change ( k << 1 , l , mid , x , y , L , R , z ) ;
	if ( y > mid ) change ( k << 1 | 1 , mid + 1 , r , x , y , L , R , z ) ;
}

int query ( int k , int l , int r , int x , int y , int L , int R ) {
	if ( x <= l && r <= y )
		return B .query ( rt [ k ] , 1 , n , L , R ) + A .query ( rt [ k ] , 1 , n , L , R ) * ( r - l + 1 ) ;
	int mid = ( l + r ) >> 1 , res = A .query ( rt [ k ] , 1 , n , L , R ) * ( min ( r , y ) - max ( x , l ) + 1 ) ;
	if ( x <= mid ) res += query ( k << 1 , l , mid , x , y , L , R ) ;
	if ( y > mid ) res += query ( k << 1 | 1 , mid + 1 , r , x , y , L , R ) ;
	return res ;
}

signed main ( ) {
	cin >> n >> q ;
	while ( q -- ) {
		int op = read ( ) , xa = read ( ) , ya = read ( ) , xb = read ( ) , yb = read ( ) ;
		if ( xa > xb ) swap ( xa , xb ) ;
		if ( ya > yb ) swap ( ya , yb ) ;
		if ( op == 1 ) {
			int val = read ( ) ;
			change ( 1 , 1 , n , xa , xb , ya , yb , val ) ;
		}
		else {
			cout << query ( 1 , 1 , n , xa , xb , ya , yb ) << '\n' ;
		}
	}
	return 0 ;
}

码风可能有点与众不同,望包含。

标签:树套,rs,求和,mid,int,read,区间,query,矩形
From: https://www.cnblogs.com/linghuabaobao/p/17104069.html

相关文章

  • C语言bug——数据帧中地址位求和——运算符优先级
     unsignedchara[30]={045F00000006 01032710000A};inttemp=a[8]<<8+a[9];按照上述计算后打印的值位0 出错原因<<优先级低于+ 因此改......
  • drf之请求和响应
    drf之请求和响应drf请求在APIView视图类中,会在执行as_view方法时重新包装request,而用到的方法时通过rest_frame.request.Request类产生了一个新的request对象。那么Requ......
  • 【CSP201312-3】最大的矩形,单调栈
    problem201312-3试题名称:最大的矩形时间限制:1.0s内存限制:256.0MB问题描述:问题描述在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1≤i≤n)个矩形的高度......
  • Servlet中设置请求和响应的编码格式
    请求数据的编码格式:1、使用String类进行数据重新编码先用浏览器的编码格式解析为字节数组,然后转为utf-8的字符串。Stringdata=newString(获取到的String信息.g......
  • 登录案例需求和分析
    登录案例需求用户登录案例需求:1.编写login.html登录页面username&password两个输入框2.使用Druid数据库连接池技术,操作mysql,day14......
  • 【YBT2023寒假Day7 C】查区间(线段树套线段树)
    查区间题目链接:YBT2023寒假Day7C题目大意给你一个序列,要你维护两种操作,区间取min和区间求第k小。思路关于区间求第k小,有一个方法,是树套树。外层线段树维护位......
  • 【闲话】2023.2.3 k次加权组合数求和
    问题引入CodeForces-932ETeamWork给出\(n,k\),求:\[\sum_{i=1}^ni^k\dbinom{n}{i}\bmodp\]\(1\len\le10^9,1\lek\le5000,p=10^9+7\)\(k=0\)二项式定理:\[......
  • P2241 统计方形(数据加强版)(矩形中的正方,长方形统计)
    统计方形(数据加强版)题目背景1997年普及组第一题题目描述有一个\(n\timesm\)方格的棋盘,求其方格包含多少正方形、长方形(不包含正方形)。输入格式一行,两个正整数\(......
  • 矩形A + B 2524
    ​​点击这里看题目链接矩形A+B​​//有n行和m列。//如果只看一行的话,它有多少个矩形呢?单个地数有m个,两个地数有m-1个……,m个地数有1个。//每一行就有:1+2+3+……+m个......
  • aijs 添加图形 线条与矩形
    varcanvas=activeDocument.groupItems.add();varpt=72/25.4;//把需要添加的图形放入列表varshapes=newArray();shapes.push(newShapeLine(0,0,20,20,0.2,......