列表

详情


NC52774. 千万别用树套树

描述

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

输入描述

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

输出描述

对于每个类型 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

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 419ms, 内存消耗: 3804K, 提交时间: 2019-10-09 16:35:42

#include <stdio.h>
const int N = 1e5+10;
int L[N], R[N];
int main()
{
	int n, q, op, l, r;
	while(scanf("%d %d", &n, &q) != EOF)
	{
		for(int i = 1; i <= n; i++) L[i] = R[i] = 0;
		for(int i = 1; i <= q; i++)
		{
			scanf("%d %d %d", &op, &l, &r);
			if(op==1)
			{
				for(int j = l; j<=n; j+=(j&-j)) L[j]++;
				for(int j = r; j<=n; j+=(j&-j)) R[j]++;
			}else{
				int res = 0;
				for(int j = l; j; j-=(j&-j)) res += L[j];
				for(int j=r-1; j; j-=(j&-j)) res -= R[j];
				printf("%d\n", res);
			}
		}
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 453ms, 内存消耗: 17160K, 提交时间: 2020-02-25 22:27:48

#include<bits/stdc++.h>
#define lb(x) (x&(-x))
using namespace std;
const int N=1e5+5;
int n,m,l[N],r[N];
void add(int *c,int i)
{
	while(i<=n)
	c[i]++,i+=lb(i);
}
int ask(int *c,int i)
{
	int res=0;
	while(i>0) res+=c[i],i-=lb(i);
	return res;
}
int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n>>m)
	{
		for(int i=1;i<=n;i++)
		l[i]=r[i]=0;
		for(int op,x,y;m--;)
		{
			cin>>op>>x>>y;
			if(op==1) add(l,x),add(r,y);
			else printf("%d\n",ask(l,x)-ask(r,y-1));
		}
	 } 
}

上一题