数列分块入门8
题意
给出一个长度为 n n n 的序列,以及 n n n 个操作,每次操作询问区间 [ l , r ] [l,r] [l,r] 内等于 c c c 的元素的个数,并将这个区间内的所有元素改为 c c c 。
解法
这是一道分块入门的题目,那当然要用分块的做法,但是一开始一不小心写了 O ( n n l o g n ) O(n\sqrt nlogn) O(nnlogn) 的算法,T飞之后一下子想不到怎么去掉 l o g log log ,看到区间赋值之后尝试了一发珂朵莉树直接AC,挺开心的。
然后这是一道分块入门的题目,那当然要用分块的做法。核心在于如何修改及查询大块。
- 首先考虑标记这个大块是否所有值相等。如果相等,只需要标记 f l a g [ i d ] = 1 flag[id]=1 flag[id]=1 ,然后修改第一个元素 a [ i d ∗ B ] a[id*B] a[id∗B] 的值即可,这个块的所有元素的值都等于 a [ i d ∗ B ] a[id*B] a[id∗B] 。相等的大块也很简单。
- 然后一开始所有块都是不相等的,每次区间内涉及的大块都会变成相等,并且最多增加两个不相等的大块,所以这个暴力修改不相等的大块的复杂度不会太大。
代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
namespace fastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->R
bool IOerror = 0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if (p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if (pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
template <class T>
inline bool R(T &x) {
bool sign = 0;
char ch = nc();
x = 0;
for (; blank(ch); ch = nc())
;
if (IOerror)
return false;
if (ch == '-')
sign = 1, ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())
x = x * 10 + ch - '0';
if (sign)
x = -x;
return true;
}
inline bool R(double &x) {
bool sign = 0;
char ch = nc();
x = 0;
for (; blank(ch); ch = nc())
;
if (IOerror)
return false;
if (ch == '-')
sign = 1, ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())
x = x * 10 + ch - '0';
if (ch == '.') {
double tmp = 1;
ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())
tmp /= 10.0, x += tmp * (ch - '0');
}
if (sign)
x = -x;
return true;
}
inline bool R(char *s) {
char ch = nc();
for (; blank(ch); ch = nc())
;
if (IOerror)
return false;
for (; !blank(ch) && !IOerror; ch = nc())
*s++ = ch;
*s = 0;
return true;
}
inline bool R(char &c) {
c = nc();
if (IOerror) {
c = -1;
return false;
}
return true;
}
template <class T, class... U>
bool R(T &h, U &... t) { return R(h) && R(t...); }
#undef OUT_SIZE
#undef BUF_SIZE
}; // namespace fastIO
using namespace fastIO;
template <class T>
void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const int64_t &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template <class T, class U>
void _W(const pair<T, U> &x) { _W(x.F), putchar(' '), _W(x.S); }
template <class T>
void _W(const vector<T> &x) {
for (auto i = x.begin(); i != x.end(); _W(*i++))
if (i != x.cbegin()) putchar(' ');
}
void W() {}
template <class T, class... U>
void W(const T &head, const U &... tail) { _W(head), putchar(sizeof...(tail) ? ' ' : '\n'), W(tail...); }
#pragma endregion
const int maxn = 1e5 + 5;
int n, B;
int a[maxn], flag[maxn];
void update(int l, int r, int c) {
int idl = l / B, idr = r / B;
if (idl == idr) {
if (flag[idl]) {
flag[idl] = 0;
rep(i, max(1, idl * B), min(n, (idl + 1) * B - 1)) a[i] = a[idl * B];
}
rep(i, l, r) a[i] = c;
} else {
if (flag[idl]) {
flag[idl] = 0;
rep(i, max(1, idl * B), min(n, (idl + 1) * B - 1)) a[i] = a[idl * B];
}
rep(i, l, (idl + 1) * B - 1) a[i] = c;
rep(id, idl + 1, idr - 1) a[id * B] = c, flag[id] = 1;
if (flag[idr]) {
flag[idr] = 0;
rep(i, max(1, idr * B), min(n, (idr + 1) * B - 1)) a[i] = a[idr * B];
}
rep(i, idr * B, r) a[i] = c;
}
}
int query(int l, int r, int c) {
int idl = l / B, idr = r / B;
int ans = 0;
if (idl == idr) {
if (flag[idl] && a[idl * B] == c)
ans += r - l + 1;
else if (!flag[idl])
rep(i, l, r) ans += (a[i] == c);
} else {
if (flag[idl] && a[idl * B] == c)
ans += (idl + 1) * B - l;
else if (!flag[idl])
rep(i, l, (idl + 1) * B - 1) ans += (a[i] == c);
rep(id, idl + 1, idr - 1) {
if (flag[id] && a[id * B] == c)
ans += B;
else if (!flag[id])
rep(i, id * B, (id + 1) * B - 1) ans += (a[i] == c);
}
if (flag[idr] && a[idr * B] == c)
ans += r - idr * B + 1;
else if (!flag[idr])
rep(i, idr * B, r) ans += (a[i] == c);
}
return ans;
}
int main() {
R(n);
B = sqrt(n);
rep(i, 1, n) R(a[i]);
rep(i, 1, n) {
int l, r, c;
R(l, r, c);
W(query(l, r, c));
update(l, r, c);
}
}
珂朵莉树版本
#pragma region
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
namespace fastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->R
bool IOerror = 0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if (p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if (pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
template <class T>
inline bool R(T &x) {
bool sign = 0;
char ch = nc();
x = 0;
for (; blank(ch); ch = nc())
;
if (IOerror)
return false;
if (ch == '-')
sign = 1, ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())
x = x * 10 + ch - '0';
if (sign)
x = -x;
return true;
}
inline bool R(double &x) {
bool sign = 0;
char ch = nc();
x = 0;
for (; blank(ch); ch = nc())
;
if (IOerror)
return false;
if (ch == '-')
sign = 1, ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())
x = x * 10 + ch - '0';
if (ch == '.') {
double tmp = 1;
ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())
tmp /= 10.0, x += tmp * (ch - '0');
}
if (sign)
x = -x;
return true;
}
inline bool R(char *s) {
char ch = nc();
for (; blank(ch); ch = nc())
;
if (IOerror)
return false;
for (; !blank(ch) && !IOerror; ch = nc())
*s++ = ch;
*s = 0;
return true;
}
inline bool R(char &c) {
c = nc();
if (IOerror) {
c = -1;
return false;
}
return true;
}
template <class T, class... U>
bool R(T &h, U &... t) { return R(h) && R(t...); }
#undef OUT_SIZE
#undef BUF_SIZE
}; // namespace fastIO
using namespace fastIO;
template <class T>
void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const int64_t &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template <class T, class U>
void _W(const pair<T, U> &x) { _W(x.F), putchar(' '), _W(x.S); }
template <class T>
void _W(const vector<T> &x) {
for (auto i = x.begin(); i != x.end(); _W(*i++))
if (i != x.cbegin()) putchar(' ');
}
void W() {}
template <class T, class... U>
void W(const T &head, const U &... tail) { _W(head), putchar(sizeof...(tail) ? ' ' : '\n'), W(tail...); }
#pragma endregion
#define IT set<node>::iterator
struct node {
int l, r;
mutable ll v;
node(int L, int R = -1, ll V = 0) : l(L), r(R), v(V) {}
bool operator<(const node &A) const { return l < A.l; }
};
set<node> s;
IT split(ll pos) { //拆区间,将区间分为[l,pos-1],[pos,r]两段
IT it = s.lower_bound(node(pos));
if (it != s.end() && it->l == pos) return it;
--it;
int L = it->l, R = it->r;
ll V = it->v;
s.erase(it);
s.insert(node(L, pos - 1, V));
return s.insert(node(pos, R, V)).first;
//返回第二个区间的地址
}
void assign_val(int l, int r, ll x) { //区间推平,全部赋值x
IT itr = split(r + 1),
itl = split(l); //划分区间,注意顺序,否则会引起itl迭代器失效
s.erase(itl, itr);
s.insert(node(l, r, x));
}
ll ranks(int l, int r, int k) { //区间第k小
vector<pair<ll, int>> vp;
IT itr = split(r + 1), itl = split(l); //划分区间
vp.clear();
for (; itl != itr; ++itl) vp.push_back({itl->v, itl->r - itl->l + 1});
sort(vp.begin(), vp.end());
for (auto it : vp) {
k -= it.second;
if (k <= 0) return it.first;
}
return 0;
}
int query(int l, int r, ll c) {
IT itr = split(r + 1), itl = split(l);
int ans = 0;
for (; itl != itr; ++itl)
if (itl->v == c) ans += itl->r - itl->l + 1;
return ans;
}
const int maxn = 1e5 + 5;
int a[maxn];
int main() {
int n;
R(n);
rep(i, 1, n) {
R(a[i]);
s.insert(node(i, i, a[i]));
}
rep(i, 1, n) {
int l, r, c;
R(l, r, c);
W(query(l, r, c));
assign_val(l, r, c);
}
}