CSU - 2170 千万别用树套树(线段树)

链接:https://ac.nowcoder.com/acm/contest/1108/H
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld

题目描述

Bobo 精通数据结构!他想维护一个线段的集合 S。初始时,S 为空。他会依次进行 q 次操作,操作有 2 种。
* 类型 1:给出 l, r,向集合 S 中插入线段 [l, r].
* 类型 2:给出 l, r,询问满足 [x,y]∈S[x, y] \in S[x,y]∈S 且 x≤l≤r≤yx \leq l \leq r \leq yx≤l≤r≤y 的线段 [x, y] 数量。
帮 Bobo 求出每次询问的答案。

输入描述:

输入文件包含多组数据,请处理到文件结束。
每组数据的第一行包含 2 个整数 n 和 q. 其中 n 表示操作中 r 的最大值。
接下来 q 行中的第 i 行包含 3 个整数 ti,li,rit_i, l_i, r_iti​,li​,ri​,表示第 i 个操作属于类型 tit_iti​,对应的参数是 lil_ili​ 和 rir_iri​.

输出描述:

对于每个类型 2 的询问,输出 1 个整数表示对应的数量。

示例1

输入

复制

1 2
1 1 1
2 1 1
4 4
1 1 4
2 2 3
1 1 4
2 2 3

输出

复制

1
1
2

备注:

* 1≤n,q≤1051 \leq n, q \leq 10^51≤n,q≤105
* ti∈{1,2}t_i \in \{1, 2\}ti​∈{1,2}
* 1≤li≤ri≤n1 \leq l_i \leq r_i \leq n1≤li​≤ri​≤n
* 对于 ti=2t_i = 2ti​=2 的操作,ri−li≤2r_i - l_i \leq 2ri​−li​≤2 成立。
* 数据组数不超过 10.

        这道题最重要的是操作2的时候ri-li<=2这个条件。我们这样想,在对于一个操作1的时候,放入l,r。这个线段l,r能够产生作用的范围是有限的:他会对结尾为l+2到r的,长度为3的操作2线段查询产生一次贡献。会对结尾为l+1到r的,长度为2的操作2的线段查询产生一次贡献.会对结尾为l到r的,长度为1的操作2的线段查询产生一次贡献。这样我们建立三个树分别维护这个信息就好了。

#include<bits/stdc++.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline bool sc(int &num){
	char in; bool IsN = false;
	in = getchar();
	if (in == EOF) return false;
	while (in != '-' && (in<'0' || in>'9')) in = getchar();
	if (in == '-') { IsN = true; num = 0; }
	else num = in - '0';
	while (in = getchar(), in >= '0'&&in <= '9') {
		num *= 10, num += in - '0';
	}
	if (IsN) num = -num;
	return true;
}
const int M = 100010;
int  lazy[M * 6][3];
void pushdown(int rt,int kind) {
	if (lazy[rt][kind]) {
		lazy[rt << 1][kind] += lazy[rt][kind];
		lazy[rt << 1 | 1][kind] += lazy[rt][kind];
		lazy[rt][kind] = 0;
	}
}
void build(int l, int r, int rt) {
	lazy[rt][0] = lazy[rt][1] = lazy[rt][2] = 0;
	if (l == r) {
		return;
	}
	int mid = (l + r) >> 1;
	build(lson); build(rson);
}

void update(int l, int r, int rt, int L,int R,int kind) {
	if (L <= l && r <= R) {
		lazy[rt][kind] += 1;
		return;
	}
	pushdown(rt, kind);
	int mid = (l + r) >> 1;
	if (L <= mid) {
		update(lson, L, R, kind);
	}
	if (R > mid) {
		update(rson, L, R, kind);
	}
	return;
}
int query(int l, int r, int rt, int x,int kind) {
	if (l == r) {
		return lazy[rt][kind];
	}
	int mid = (l + r) >> 1;
	pushdown(rt, kind);
	if (x <= mid)return query(lson, x, kind);
	else return query(rson, x, kind);
}
int main() {
	int n, m;
	while (~scanf("%d%d",&n,&m)) {
		build(1, n, 1);
		while (m--) {
			int a, b, c;
			sc(a); sc(b); sc(c);
			if (a == 1) {
				int len = c - b + 1;
				if (len == 1) {
					update(1, n, 1, b, b, 0);
				}
				else if (len == 2) {
					update(1, n, 1, b, c, 0);
					update(1, n, 1, c, c, 1);
				}
				else {
					update(1, n, 1, b, c, 0);
					update(1, n, 1, b + 1, c, 1);
					update(1, n, 1, b + 2, c, 2);
				}
			}
			else {
				printf("%d\n", query(1, n, 1, c, c - b));
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/chenshibo17/article/details/101994400