Luogu P2184 贪婪大陆
题目
维护一个 \(n\) 项的序列,有 \(m\) 个操作,为以下两种之一:
1 l r
表示在 \([l,r]\) 这段区间布上一种地雷2 l r
表示询问 \([l,r]\) 区间内共有多少种地雷
分析
可以把区间的左端点和右端点分开处理:如果某种地雷在 \([l,r]\) 内存在,那么这种地雷的左端点一定小于等于 \(r\) ,且右端点一定大于等于 \(l\) ,所以答案就是小于等于 \(r\) 的左端点数减去小于 \(l\) 的右端点数
代码
#include<bits/stdc++.h>
#define ls(k) k << 1
#define rs(k) k << 1 | 1
using namespace std;
const int MAX_N = 100000 + 5;
int sum1[MAX_N * 4], sum2[MAX_N * 4];
void modify1(int k, int l, int r, int x, int v)
{
if(l == r && l == x) {
sum1[k] += v;
return;
}
int m = (l + r) >> 1;
if(x <= m)
modify1(ls(k), l, m, x, v);
else
modify1(rs(k), m + 1, r, x, v);
sum1[k] = sum1[ls(k)] + sum1[rs(k)];
}
void modify2(int k, int l, int r, int x, int v)
{
if(l == r && l == x) {
sum2[k] += v;
return;
}
int m = (l + r) >> 1;
if(x <= m)
modify2(ls(k), l, m, x, v);
else
modify2(rs(k), m + 1, r, x, v);
sum2[k] = sum2[ls(k)] + sum2[rs(k)];
}
int query1(int k, int l, int r, int x, int y)
{
if(l >= x && r <= y)
return sum1[k];
int m = (l + r) >> 1;
int res = 0;
if(x <= m)
res += query1(ls(k), l, m, x, y);
if(m + 1 <= y)
res += query1(rs(k), m + 1, r, x, y);
return res;
}
int query2(int k, int l, int r, int x, int y)
{
if(l >= x && r <= y)
return sum2[k];
int m = (l + r) >> 1;
int res = 0;
if(x <= m)
res += query2(ls(k), l, m, x, y);
if(m + 1 <= y)
res += query2(rs(k), m + 1, r, x, y);
return res;
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
while(m--) {
int q, l, r;
scanf("%d%d%d", &q, &l, &r);
if(q == 1) {
modify1(1, 1, n, l, 1);
modify2(1, 1, n, r, 1);
} else {
if(l == 1)
printf("%d\n", query1(1, 1, n, 1, r));
else
printf("%d\n", query1(1, 1, n, 1, r) - query2(1, 1, n, 1, l - 1));
}
}
return 0;
}