UVA-11297 Census(线段树套线段树)

题目大意:二维空间点修改,询问矩形区域最值。

题目分析:还是比较简单的。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
# define LL long long
# define mid (l+(r-l)/2)

const int N=500;
const int INF=0x7fffffff;

int maxn[N*4+5][N*4+5];
int minn[N*4+5][N*4+5];

bool leaf;

void pushUpY(int id,int rt)
{
	maxn[id][rt]=max(maxn[id][rt<<1],maxn[id][rt<<1|1]);
	minn[id][rt]=min(minn[id][rt<<1],minn[id][rt<<1|1]);
}

void buildY(int id,int rt,int l,int r)
{
	if(l==r){
		if(leaf){
			int a;
			scanf("%d",&a);
			maxn[id][rt]=minn[id][rt]=a;
		}else{
			maxn[id][rt]=max(maxn[id<<1][rt],maxn[id<<1|1][rt]);
			minn[id][rt]=min(minn[id<<1][rt],minn[id<<1|1][rt]);
		}
	}else{
		buildY(id,rt<<1,l,mid);
		buildY(id,rt<<1|1,mid+1,r);
		pushUpY(id,rt);
	}
}

void buildX(int rt,int l,int r,int m)
{
	if(l==r){
		leaf=true;
		buildY(rt,1,1,m);
	}else{
		buildX(rt<<1,l,mid,m);
		buildX(rt<<1|1,mid+1,r,m);
		leaf=false;
		buildY(rt,1,1,m);
	}
}

void updateY(int id,int rt,int l,int r,int p,int v)
{
	if(l==r){
		if(leaf) maxn[id][rt]=minn[id][rt]=v;
		else{
			maxn[id][rt]=max(maxn[id<<1][rt],maxn[id<<1|1][rt]);
			minn[id][rt]=min(minn[id<<1][rt],minn[id<<1|1][rt]);
		}
	}else{
		if(p<=mid) updateY(id,rt<<1,l,mid,p,v);
		else updateY(id,rt<<1|1,mid+1,r,p,v);
		pushUpY(id,rt);
	}
}

void updateX(int rt,int l,int r,int p1,int p2,int v,int m)
{
	if(l==r){
		leaf=true;
		updateY(rt,1,1,m,p2,v);
	}else{
		if(p1<=mid) updateX(rt<<1,l,mid,p1,p2,v,m);
		else updateX(rt<<1|1,mid+1,r,p1,p2,v,m);
		leaf=false;
		updateY(rt,1,1,m,p2,v);
	}
}

void queryY(int id,int rt,int l,int r,int L,int R,int &mx,int &mn)
{
	if(L<=l&&r<=R){
		mx=max(mx,maxn[id][rt]);
		mn=min(mn,minn[id][rt]);
	}else{
		if(L<=mid) queryY(id,rt<<1,l,mid,L,R,mx,mn);
		if(R>mid) queryY(id,rt<<1|1,mid+1,r,L,R,mx,mn);
	}
}

void queryX(int rt,int l,int r,int L,int R,int L1,int R1,int &mx,int &mn,int m)
{
	if(L<=l&&r<=R){
		queryY(rt,1,1,m,L1,R1,mx,mn);
	}else{
		if(L<=mid) queryX(rt<<1,l,mid,L,R,L1,R1,mx,mn,m);
		if(R>mid) queryX(rt<<1|1,mid+1,r,L,R,L1,R1,mx,mn,m);
	}
}

int main()
{
	int n,q,a,b,c,d;
	char op[2];
	while(~scanf("%d",&n))
	{
		buildX(1,1,n,n);
		scanf("%d",&q);
		while(q--)
		{
			scanf("%s",op);
			if(op[0]==‘c‘){
				scanf("%d%d%d",&a,&b,&c);
				updateX(1,1,n,a,b,c,n);
			}else if(op[0]==‘q‘){
				scanf("%d%d%d%d",&a,&b,&c,&d);
				int ansA=-INF,ansB=INF;
				queryX(1,1,n,a,c,b,d,ansA,ansB,n);
				printf("%d %d\n",ansA,ansB);
			}
		}
	}
	return 0;
}

  

时间: 2024-08-07 16:47:04

UVA-11297 Census(线段树套线段树)的相关文章

Uva 11297 Census,二维线段树,板子

维护二维矩阵. q  x1, y1, x2, y2 :   查询x1<=x<=x2, y1<=y<=y2的格子(x,y)的最大值和最小值. c    x, y, v:    修改(x,y) = v. 矩阵大小(n,m<=500). 查询次数q<=40000. #include<algorithm> using namespace std; const int INF = 1<<30; const int maxn = 2000 + 10; int

[BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log n). 代码 树状数组套线段树 #include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> usin

【vijos】1750 建房子(线段树套线段树+前缀和)

https://vijos.org/p/1750 是不是我想复杂了.... 自己yy了个二维线段树,然后愉快的敲打. 但是wa了两法.......sad 原因是在处理第二维的更新出现了个小问题,sad. void pushup1(int x) { for1(i, 1, mm<<2) mn[x][i]=min(mn[lc][i], mn[rc][i]); } 这里注意是mm*4...我该好好想想了..这是在dbg的时候找出来的问题.sad. 我觉得很奇怪,线段树的底层节点一共就mm个,那么整棵树

【bzoj4785】[Zjoi2017]树状数组 线段树套线段树

题目描述 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种: 1 x,表示将 Ax 变成 (Ax + 1) mod 2. 2 l r,表示询问 sigma(Ai) mod 2,L<=i<=r 尽管那个时候的可怜非常的 simple,但是她还是发现这题可以用树状数组做.当时非常young 的她写了如下的算法: 1: function Add(x

hdu-4819-线段树套线段树

http://acm.hdu.edu.cn/showproblem.php?pid=4819 给出一个N*N的矩阵,每次询问一个m*m的子矩阵里的floor((maxv+minv)/2)并把中间的元素修改为这个值. 线段树套线段树,第一层X表示对行建立的线段树,内层表示对Y也就是列建立的线段树. 分别对X和Y建立相应的函数来完成操作,当更新X树的节点时,再更新完当前X的节点的左右儿子之后,回头对X的这个节点对应的Y树进行更新,相当于X的左右儿子里的Y树来更新X的Y树,能理解这一点就很简单了. 1

ZJOI 2017 树状数组(线段树套线段树)

题意 http://uoj.ac/problem/291 思路 不难发现,九条カレン醬所写的树状数组,在查询区间 \([1,r]\) 的时候,其实在查询后缀 \([r,n]\) :在查询 \([l,r](l\neq1)\) 的时候,则是在查询 \([l-1,r-1]\) .那么在查询 \([1,r]\) 的时候,只需要询问 \(r\) 的前后缀异或是否相等:在查询 \([l,r](l\neq 1)\) 的时候,只需要询问 \(a[l-1],a[r]\) 是否相等. 考虑 \(O(n^2)\) 的

HDU - 5390 tree 线段树套字典树 (看题解)

HDU - 5390 看到的第一感觉就是树链剖分 + 线段树套字典树, 感觉复杂度不太对. 其实这种路径其实很特殊, 一个点改变只会影响它儿子到根的路径, 并且这种求最优值问题可以叠加. 所以我们修改的时候对对应dfs序打标记, 询问的时候在线段树上从上往下对每个对应区间求个最优值. 这样还会被卡MLE.. 需要分层优化一下. #pragma GCC optimize(2) #pragma GCC optimize(3) #include<bits/stdc++.h> #define LL l

BZOJ 3217 ALOEXT 替罪羊树套Trie树

题目大意:维护一个序列,支持以下操作: 1.在某个位置插入一个数 2.删除某个位置上的数 3.修改某个位置上的数 4.求某段区间中的次大值与区间中另一个数的异或值的最大值 强制在线 替罪羊树套Trie树...终于尼玛A了...7.4KB的大代码啊- - 插入和修改同带插入区间k小值 删除要打标记不能直接删 删除的时候注意 删除导致的不平衡不要重建 否则复杂度无法保证 因此每个节点维护一个max_size代表历史size最大值 判断不平衡时用这个变量来判断即可 注意访问替罪羊树的时候一定要判断当前

【bzoj3217】ALOEXT 替罪羊树套Trie树

题目描述 taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手. 突然有一天,taorunz来到了一个密室,里面放着一排可移动存储器,存储器里有非常珍贵的OI资料……不过比较特殊的是,每个存储器上都写着一个非负整数.taorunz很高兴,要把所有的存储器都拿走(taorunz的智商高达500,他一旦弄走了这里的所有存储器,在不久到来的AHOI和NOI中……你懂的).不过这时有一个声音传来:“你只能拿走这里的一个存储器,而且还不能直

BZOJ 3065 带插入区间K小值 替罪羊树套线段树

题目大意:带插入,单点修改的区间k小值在线查询. 思路:本年度做过最酸爽的题. 树套树的本质是一个外层不会动的树来套一个内层会动(或不会动)的树.两个树的时间复杂度相乘也就是差不多O(nlog^2n)左右.但是众所周知,高级数据结构经常会伴有庞大的常数,所以一般来说树套树的常数也不会小到哪去.所以在做这种题的时候先不要考虑常数的问题... 为什么要用替罪羊树呢?因为一般的平衡树都是会动的,这就很难办了.外层的树动了之后,内层的树肯定也是会动的.很显然,一般的二叉平衡树会经常会旋转,这样在动外层的