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 的每次询问,输出一个答案(单独一行),表示当前区间地雷总数。
输入输出样例
5 4
1 1 3
2 2 5
1 2 4
2 3 5
输出
1
2
题目分析
将区间修改改为单点修改,即只记录起点和终点。如需要在【1,3】中种下地雷,则记录起点1的地雷数++,终点3的地雷数++。求解【l,r】的地雷数问题就转化为求解【1,r】的所有起点地雷-以【1,l-1】为终点的地雷数。
用线段树来维护。
点击查看代码
#include<iostream>
#include<vector>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200020
#define ls u<<1
#define rs u<<1|1
int d;
struct tree
{
int l,r;
ll sum1,sum2;//sum1维护起点地雷,sum2维护终点地雷
}tr[N*4];
void pushup(int u)
{
tr[u].sum1=tr[ls].sum1+tr[rs].sum1;
tr[u].sum2=tr[ls].sum2+tr[rs].sum2;
return ;
}
void build(int u,int l,int r)
{
tr[u]={l,r,0,0};
if(l==r)
{
return ;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void change(int x,int u,int f)
{
if(tr[u].l==x&&tr[u].r==x)
{
if(f)
tr[u].sum1+=1;
else
tr[u].sum2+=1;
return ;
}
int m=tr[u].l+tr[u].r>>1;
if(x<=m)
change(x,ls,f);
else
change(x,rs,f);
pushup(u);
}
int query1(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r)
return tr[u].sum1;
int m=tr[u].l+tr[u].r>>1;
int ans=0;
if(l<=m) ans+=query1(ls,l,r);
if(r>m) ans+=query1(rs,l,r);
return ans;
}
int query2(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r)
return tr[u].sum2;
int m=tr[u].l+tr[u].r>>1;
int ans=0;
if(l<=m) ans+=query2(ls,l,r);
if(r>m) ans+=query2(rs,l,r);
return ans;
}
int main()
{
cin.tie(NULL);
cout.tie(nullptr);
ios_base::sync_with_stdio(false);
int q,m,n;
int c,x,y;
int t;
cin>>n>>m;
build(1,1,n);
for(int i=1;i<=m;i++)
{
cin>>c>>x>>y;
if(c==1)
{
change(x,1,1);
change(y,1,0);
}
else {
cout<<query1(1,1,y)-query2(1,1,x-1)<<'\n';
}
}
return 0;
}

浙公网安备 33010602011771号