校门外的树

测试地址:

【题目描述】

原题来自:Vijos P1448

校门外有很多树,学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两种操作:

K=1,读入 l,r 表示在 l 到 r 之间种上一种树,每次操作种的树的种类都不同;

K=2,读入 l,r 表示询问 l 到 r 之间有多少种树。

注意:每个位置都可以重复种树。

【输入】

第一行 n,m 表示道路总长为 n,共有 m 个操作;

接下来 m 行为 m 个操作。

【输出】

对于每个 k=2 输出一个答案。

【输入样例】

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

【输出样例】

1
2

【提示】

数据范围与提示:

对于 20 的数据,1 ≤ n,m ≤ 100;

对于 %60 的数据,1 ≤ n ≤ 10^3,1 ≤ m ≤ 5×10^4;

对于 %100 的数据,1 ≤ n,m ≤ 5×10^4,保证 l,r > 0。

【思路】

相当与给你一大堆线段,问给你的区间与多少线段有交点

于是有了一种十分魔性的方法:括号法

假设有一个长度为 10 的数轴,我们要将区间 [ 2 , 5 ] 中种树,这时,我们将 2 处放一个左括号 ” ( ” ,5处放一个 ” )” ,表示区间 [ 2 , 5 ]种了树。

查询某个区间树的种类,如区间[ 3 , 10],只需统计10之前(包括10)有多少个‘(’,统计3之前有多少个‘)’,(不包括3)。
然后维护一个树状数组就ok了

【AC代码】

#include<cstdio>
const int maxn=1e6+7;
int n, m;
int a[maxn], b[maxn];
int lowbit(int x){	return x&(-x);	}
void update(int x, int a[]){
	for(int i = x; i <= n; i+=lowbit(i))
		a[i]++;
}
int sum(int x, int a[]){
	int sumn = 0;
	for(int i = x; i > 0; i-=lowbit(i)){
		sumn += a[i];
	}
	return sumn;
}
int main(){
	scanf("%d%d", &n, &m);
	while(m--){
		int k, l, r;
		scanf("%d%d%d", &k, &l, &r);
		if(k == 1) {
			update(l, a);  //左括号 
			update(r, b);  //右括号 
		}
		else{
			printf("%d\n", sum(r, a)-sum(l-1, b));
		}
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值