【洛谷 P2184】贪婪大陆
好几天没更新了
这几天还是在做线段树的题目
后面,可能做点DP?
这块不是很熟的样子
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\)。
解法&&个人感想
一开始,我们想着能不能直接用区间修改来做这道题,但是没办法
所以,我们要把我们要求的东西转化成要维护的东西
想到,区间的颜色数=\(R\)之前的区间开头数-\(L\)之前的区间结尾数
因此,只需要维护区间的开头和区间的结尾就可以了
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x&(-x))
#define maxn 100005
using namespace std;
struct SegmentTree{
int l,r,st,fi;
}tree[4*maxn];
int n,m;
int op,x,y;
void build(int x,int l,int r){
tree[x].l=l;tree[x].r=r;
if(tree[x].l==tree[x].r){
tree[x].st=tree[x].fi=0;
return ;
}
int mid=(tree[x].l+tree[x].r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
tree[x].st=tree[x*2].st+tree[x*2+1].st;
tree[x].fi=tree[x*2].fi+tree[x*2+1].fi;
return ;
}
void change_1(int x,int n,int k){
if(tree[x].l==tree[x].r){
tree[x].st+=k;
return ;
}
int mid=(tree[x].l+tree[x].r)/2;
if(n<=mid) change_1(x*2,n,k);
else change_1(x*2+1,n,k);
tree[x].st=tree[x*2].st+tree[x*2+1].st;
return ;
}
void change_2(int x,int n,int k){
if(tree[x].l==tree[x].r){
tree[x].fi+=k;
return ;
}
int mid=(tree[x].l+tree[x].r)/2;
if(n<=mid) change_2(x*2,n,k);
else change_2(x*2+1,n,k);
tree[x].fi=tree[x*2].fi+tree[x*2+1].fi;
return ;
}
int query_1(int x,int l,int r){
if(l<=tree[x].l&&tree[x].r<=r) return tree[x].st;
int mid=(tree[x].l+tree[x].r)/2;
int ans=0;
if(l<=mid) ans+=query_1(x*2,l,r);
if(r>mid) ans+=query_1(x*2+1,l,r);
return ans;
}
int query_2(int x,int l,int r){
if(l<=tree[x].l&&tree[x].r<=r) return tree[x].fi;
int mid=(tree[x].l+tree[x].r)/2;
int ans=0;
if(l<=mid) ans+=query_2(x*2,l,r);
if(r>mid) ans+=query_2(x*2+1,l,r);
return ans;
}
int main(){
cin>>n>>m;
build(1,1,n);
for(int i=1;i<=m;i++){
cin>>op;
if(op==1){
cin>>x>>y;
change_1(1,x,1);
change_2(1,y,1);
}
else{
cin>>x>>y;
int ans_1=query_1(1,1,y);
int ans_2=query_2(1,1,x-1);
cout<<ans_1-ans_2<<endl;
}
}
system("pause");
return 0;
}
后半学期,也请各位继续关注:
《我的青春线代物语果然有问题》
《高数女主养成计划》
《程设の旅》
《青春猪头少年不会梦到多智能体吃豆人》
《某Linux的开源软件》
《Charlotte太空探索》
还有——
《我的算法竞赛不可能这么可爱》
本期到此结束!

浙公网安备 33010602011771号