P2184 贪婪大陆

题目背景

面对蚂蚁们的疯狂进攻,小 FF 的 Tower defence 宣告失败……人类被蚂蚁们逼到了 Greed Island 上的一个海湾。现在,小 FF 的后方是一望无际的大海,前方是变异了的超级蚂蚁。小 FF 还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造 SCV 布置地雷以阻挡蚂蚁们的进攻。

题目描述

小 FF 最后一道防线是一条长度为 \(n\) 的战壕,小 FF 拥有无数多种地雷,而 SCV 每次可以在 \([L, R]\) 区间埋放同一种不同于之前已经埋放的地雷。由于情况已经十万火急,小 FF 在某些时候可能会询问你在 \([L',R']\) 区间内有多少种不同的地雷,他希望你能尽快的给予答复。

输入格式

第一行为两个整数 \(n\)\(m\)\(n\) 表示防线长度,\(m\) 表示 SCV 布雷次数及小 FF 询问的次数总和。

接下来有 \(m\) 行,每行三个整数 \(q,l,r\)

  • \(q=1\),则表示 SCV 在 \([l, r]\) 这段区间布上一种地雷;
  • \(q=2\),则表示小 FF 询问当前 \([l, r]\) 区间总共有多少种地雷。

输出格式

对于小 FF 的每次询问,输出一个答案(单独一行),表示当前区间地雷总数。

样例 #1

样例输入 #1

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

样例输出 #1

1
2

提示

数据规模与约定

  • 对于 \(30\%\) 的数据,\(0 \le n\)\(m \le 1000\)
  • 对于 \(100\%\) 的数据,\(0 \le n\)\(m \le 10^5\)

分析

区间加,区间线段覆盖

考虑差分,对于区间加 \([l,r]\),令 \(sum[0][l-1]++,sum[1][r]++\)

对于查询区间 \([l,r]\),答案及为:

\[\sum_{i=1}^{y}sum[0][i]-\sum_{i=1}^{x-1}sum[1][i] \]

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
	return x*f;
}
int sum[2][100005<<2];
int n,m;
void pushup(int num,int k){sum[k][num]=sum[k][num<<1]+sum[k][num<<1|1];}
void update(int l,int r,int num,int x,int k){
	if(l==r){++sum[k][num];return;}
	int mid=l+r>>1;
	if(x<=mid)update(l,mid,num<<1,x,k);
	else update(mid+1,r,num<<1|1,x,k);
	pushup(num,k);
}
int query(int l,int r,int num,int x,int y,int k){
	if(x>r||y<l)return 0;
	if(x<=l&&r<=y)return sum[k][num];
	int mid=l+r>>1;
	return query(l,mid,num<<1,x,y,k)+query(mid+1,r,num<<1|1,x,y,k);
}
signed main(){
	n=read(),m=read();
	for(int i=1,opt,x,y;i<=m;i++){
		opt=read(),x=read(),y=read();
		if(opt==1)update(1,n,1,x,0),update(1,n,1,y,1);
		else printf("%lld\n",query(1,n,1,1,y,0)-query(1,n,1,1,x-1,1));
	}
	return 0;
}
posted @ 2023-06-24 13:53  alex_liu09  阅读(16)  评论(0)    收藏  举报