【线段树】 HDOJ 5283 Senior's Fish

附上BC的官方题解。。。
题目关键在于在x轴和y轴上,鱼的坐标变化都是单调的,因为
   
   
    
    d
   
   是正值。
我们把在一个矩形内部有多少个点的询问拆分成四个在某个点的左下角
有多少个点的询问,然后用一棵线段树维护鱼的x坐标,一棵线段树维
护鱼的y坐标。对于移动操作,在对应的线段树上进行区间更新,更新
完成后询问该区间内的最大值,若最大值超过了我们关心的值,那么
这个点就可以删掉了,删除的方法可以通过在对应的线段树上把值设
为
   
   
    
    INF
   
   ,同时继续询问直到最大值不大于我们关心的值为止。那
么我们就可以实时维护当前在我们关心的点左下角的点有哪些了,这
可以再借助于一个树状数组。这样子作四遍我们就能得到最终的答案
了。由于每一次的过程中每个点只会被删除一次,所以复杂度
是
   
   
    
    O((n+q)logn))
   
   
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 100005
#define maxm 100005
#define eps 1e-7
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL; 
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

struct Point
{
	int x, y;
	Point(int x = 0, int y = 0) : x(x), y(y) {}
}point[4], fish[maxn];

int xmaxv[4][maxn << 2];
int ymaxv[4][maxn << 2];
int xlazy[4][maxn << 2];
int ylazy[4][maxn << 2];
int idx[4][maxn << 2];
int idy[4][maxn << 2];
int Sum[4][maxn << 2];
int a[maxn];
int b[maxn];
int n, m;

void pushup(int maxv[], int id[], int o)
{
	if(maxv[ls] > maxv[rs]) maxv[o] = maxv[ls], id[o] = id[ls];
	else maxv[o] = maxv[rs], id[o] = id[rs];
}

void pushup(int sum[], int o)
{
	sum[o] = sum[ls] + sum[rs];
}

void pushdown(int maxv[], int lazy[], int o)
{
	if(lazy[o]) {
		maxv[ls] += lazy[o];
		maxv[rs] += lazy[o];
		lazy[ls] += lazy[o];
		lazy[rs] += lazy[o];
		lazy[o] = 0;
	}
}

void build(int maxv[], int lazy[], int id[], int data[], int o, int L, int R)
{
	lazy[o] = 0;
	if(L == R) {
		maxv[o] = data[L];
		id[o] = L;
		return;
	}
	int mid = (L + R) >> 1;
	build(maxv, lazy, id, data, lson);
	build(maxv, lazy, id, data, rson);
	pushup(maxv, id, o);
}

void build(int sum[], int o, int L, int R)
{
	if(L == R) {
		sum[o] = 1;
		return;
	}
	int mid = (L + R) >> 1;
	build(sum, lson);
	build(sum, rson);
	pushup(sum, o);
}

void update(int maxv[], int lazy[], int id[], int o, int L, int R, int q)
{
	if(L == R) {
		maxv[o] = -INF;
		return;
	}
	pushdown(maxv, lazy, o);
	int mid = (L + R) >> 1;
	if(q <= mid) update(maxv, lazy, id, lson, q);
	else update(maxv, lazy, id, rson, q);
	pushup(maxv, id, o);
}

void update(int sum[], int o, int L, int R, int q)
{
	if(L == R) {
		sum[o] = 0;
		return;
	}
	int mid = (L + R) >> 1;
	if(q <= mid) update(sum, lson, q);
	else update(sum, rson, q);
	pushup(sum, o);
}

void update(int maxv[], int lazy[], int id[], int o, int L, int R, int ql, int qr, int d)
{
	if(ql <= L && qr >= R) {
		maxv[o] += d;
		lazy[o] += d;
		return;
	}
	pushdown(maxv, lazy, o);
	int mid = (L + R) >> 1;
	if(ql <= mid) update(maxv, lazy, id, lson, ql, qr, d);
	if(qr > mid) update(maxv, lazy, id, rson, ql, qr, d);
	pushup(maxv, id, o);
}

bool check(int rt, int flag)
{
	if(flag == 0) {
		if(xmaxv[rt][1] > point[rt].x) {
			update(Sum[rt], 1, 1, n, idx[rt][1]);
			update(xmaxv[rt], xlazy[rt], idx[rt], 1, 1, n, idx[rt][1]);
			return true;
		}
		return false;
	}
	else {
		if(ymaxv[rt][1] > point[rt].y) {
			update(Sum[rt], 1, 1, n, idy[rt][1]);
			update(ymaxv[rt], ylazy[rt], idy[rt], 1, 1, n, idy[rt][1]);
			return true;
		}
		return false;
	}
}

int query(int sum[], int o, int L, int R, int ql, int qr)
{
	if(ql <= L && qr >= R) return sum[o];
	int mid = (L + R) >> 1, ans = 0;
	if(ql <= mid) ans += query(sum, lson, ql, qr);
	if(qr > mid) ans += query(sum, rson, ql, qr);
	return ans;
}

void solve1()
{
	int l, r, d;
	scanf("%d%d%d", &l, &r, &d);
	for(int i = 0; i < 4; i++) update(xmaxv[i], xlazy[i], idx[i], 1, 1, n, l, r, d);
	for(int i = 0; i < 4; i++) while(check(i, 0));
}

void solve2()
{
	int l, r, d;
	scanf("%d%d%d", &l, &r, &d);
	for(int i = 0; i < 4; i++) update(ymaxv[i], ylazy[i], idy[i], 1, 1, n, l, r, d);
	for(int i = 0; i < 4; i++) while(check(i, 1));
}

void solve3()
{
	int l, r;
	scanf("%d%d", &l, &r);
	int res = query(Sum[0], 1, 1, n, l, r) + query(Sum[3], 1, 1, n, l, r);
	res -= query(Sum[1], 1, 1, n, l, r) + query(Sum[2], 1, 1, n, l, r);
	printf("%d\n", res);
}

void work()
{
	int xx1, yy1, xx2, yy2;
	scanf("%d", &n);
	scanf("%d%d%d%d", &xx1, &yy1, &xx2, &yy2);
	point[0] = Point(xx1 - 1, yy1 - 1);
	point[1] = Point(xx1 - 1, yy2);
	point[2] = Point(xx2, yy1 - 1);
	point[3] = Point(xx2, yy2);
	
	for(int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]);
	for(int i = 0; i < 4; i++) {
		build(xmaxv[i], xlazy[i], idx[i], a, 1, 1, n);
		build(ymaxv[i], ylazy[i], idy[i], b, 1, 1, n);
		build(Sum[i], 1, 1, n);
	}
	for(int i = 0; i < 4; i++) while(check(i, 0));
	for(int i = 0; i < 4; i++) while(check(i, 1));

	scanf("%d", &m);

	while(m--) {
		int op;
		scanf("%d", &op);
		if(op == 1) solve1();
		if(op == 2) solve2();
		if(op == 3) solve3();
	}
}

int main()
{
	int _;
	scanf("%d", &_);
	while(_--) work();
	
	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值