社区讨论
MnZn妹子,刚学CDQ,RE/WA/TLE求调
P4690[Ynoi Easy Round 2016] 镜中的昆虫参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @lo3iut7y
- 此快照首次捕获于
- 2023/10/24 07:21 2 年前
- 此快照最后确认于
- 2023/10/24 07:21 2 年前
写代码彻底弃疗了……一眼全是RE/WA/TLE就没个AC……求大佬帮忙看看哪里写挂了……/kk
CPP#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <set>
int N, M, A[100010], pre[100010], ans[100010];
namespace BinaryIndexedTree
{
class BinaryIndexedTree
{
public:
int n, tr[100010];
int lowbit(int x)
{
return x & (-x);
}
void add(int x, int v)
{
for (int i = x; i <= n; i += lowbit(i))
tr[i] += v;
}
int query(int x)
{
int res = 0;
for (int i = x; i; i -= lowbit(i))
res += tr[i];
return res;
}
} BIT;
}
namespace CDQDivide
{
int nodeCnt;
struct Node
{
int type, time, x, y, flag;
Node() {}
Node(int type, int time, int x, int y, int flag) : type(type), time(time), x(x), y(y), flag(flag) {}
} node[3000010];
void CDQ(int l, int r)
{
if (l == r)
return;
int mid = (l + r) >> 1;
CDQ(l, mid);
std::sort(node + l, node + r + 1, [](Node a, Node b) -> bool
{
if (a.time == b.time)
return a.type < b.type;
return a.time < b.time;
});
std::sort(node + l, node + mid + 1, [](Node a, Node b) -> bool
{
if (a.x == b.x)
return a.y < b.y;
return a.x < b.x;
});
std::sort(node + mid + 1, node + r + 1, [](Node a, Node b) -> bool
{
if (a.x == b.x)
return a.y < b.y;
return a.x < b.x;
});
for (int i = l, j = mid + 1; j <= r; ++ j)
{
if (node[j].type == 1)
continue;
while (i <= mid && node[i].x <= node[j].x)
{
if (node[i].type == 1)
BinaryIndexedTree::BIT.add(node[i].y + 1, node[i].flag);
++ i;
}
ans[node[j].time] += node[j].flag * BinaryIndexedTree::BIT.query(node[j].y + 1);
}
for (int i = l, j = mid + 1; j <= r; ++ j)
{
if (node[j].type == 1)
continue;
while (i <= mid && node[i].x <= node[j].x)
{
if (node[i].type == 1)
BinaryIndexedTree::BIT.add(node[i].y + 1, -node[i].flag);
++ i;
}
}
std::sort(node + l, node + r + 1, [](Node a, Node b) -> bool
{
return a.time < b.time;
});
CDQ(mid + 1, r);
}
}
namespace ChthollyTree
{
class ChthollyTree
{
public:
struct Node
{
int l, r;
mutable int v;
Node(int l, int r, int v) : l(l), r(r), v(v) {}
bool operator < (const Node &other) const
{
return l < other.l;
}
} ;
std::set <Node> ODT;
auto split(int x)
{
auto it = std::prev(ODT.upper_bound(Node(x, 0, 0)));
if (it->l == x)
return it;
int l = it->l, r = it->r, v = it->v;
ODT.erase(it);
ODT.insert(Node(l, x - 1, v));
return ODT.insert(Node(x, r, v)).first;
}
} ODT;
class ChthollyTreeColor : ChthollyTree
{
public:
struct Node
{
int l, r;
Node(int l, int r) : l(l), r(r) {}
bool operator < (const Node &other) const
{
return l < other.l;
}
} ;
std::set <Node> ODT;
} ODTColor[200010];
// 初始化 ODT,初始化 pre
void init()
{
for (int i = 1; i <= N; ++ i)
{
ODT.ODT.insert(ChthollyTree::Node(i, i, A[i]));
ODTColor[A[i]].ODT.insert(ChthollyTreeColor::Node(i, i));
}
for (int i = 1; i <= N; ++ i)
{
auto it = ODTColor[A[i]].ODT.lower_bound(ChthollyTreeColor::Node(i, i));
if (it == ODTColor[A[i]].ODT.begin())
pre[i] = 0;
else
pre[i] = std::prev(it)->l;
}
}
// 区间修改,维护 pre
void modifyAssign(int time, int l, int r, int x)
{
auto itR = ODT.split(r + 1), itL = ODT.split(l);
std::set <int> needUpdate; // 存下所有需要修改的位置
for (auto it = itL; it != itR; ++ it)
{
needUpdate.insert(it->l);
using ChthollyTreeColorNode = ChthollyTreeColor::Node;
auto next = std::next(ODTColor[it->v].ODT.lower_bound(ChthollyTreeColorNode(it->l, it->r)));
if (next != ODTColor[it->v].ODT.end())
needUpdate.insert(next->l);
ODTColor[it->v].ODT.erase(std::prev(next));
}
ODT.ODT.erase(itL, itR);
using ChthollyTreeNode = ChthollyTree::ChthollyTree::Node;
ODT.ODT.insert(ChthollyTreeNode(l, r, x));
using ChthollyTreeColorNode = ChthollyTreeColor::Node;
auto newPos = ODTColor[x].ODT.insert(ChthollyTreeColorNode(l, r)).first;
if (std::next(newPos) != ODTColor[x].ODT.end())
needUpdate.insert(std::next(newPos)->l);
for (int pos : needUpdate)
{
int v = ODT.ODT.lower_bound(ChthollyTreeNode(pos, 0, 0))->v;
int &nodeCnt = CDQDivide::nodeCnt;
CDQDivide::Node *node = CDQDivide::node;
node[ ++ nodeCnt] = CDQDivide::Node(1, time, pos, pre[pos], -1);
auto it = std::prev(ODTColor[v].ODT.upper_bound(ChthollyTreeColorNode(pos, 0)));
if (pos == it->l)
{
if (it == ODTColor[v].ODT.begin())
{
pre[pos] = 0;
node[ ++ nodeCnt] = CDQDivide::Node(1, time, pos, 0, 1);
}
else
{
pre[pos] = std::prev(it)->r;
node[ ++ nodeCnt] = CDQDivide::Node(1, time, pos, pre[pos], 1);
}
}
else
{
pre[pos] = pos - 1;
node[ ++ nodeCnt] = CDQDivide::Node(1, time, pos, pos - 1, 1);
}
}
}
}
namespace Prework
{
struct Operation
{
int type, time, l, r, x;
} operation[100010];
// 读入、离散化、树状数组定大小
void dataPreprocess()
{
scanf("%d%d", &N, &M);
BinaryIndexedTree::BIT.n = 100000;
std::vector <int> all;
for (int i = 1; i <= N; ++ i)
{
scanf("%d", &A[i]);
all.push_back(A[i]);
}
for (int i = 1; i <= M; ++ i)
{
int op;
scanf("%d", &op);
if (op == 1)
{
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
all.push_back(x);
operation[i] = {1, i, l, r, x};
}
else
{
int l, r;
scanf("%d%d", &l, &r);
operation[i] = {2, i, l, r};
}
}
std::sort(all.begin(), all.end());
all.erase(std::unique(all.begin(), all.end()), all.end());
for (int i = 1; i <= N; ++ i)
A[i] = std::lower_bound(all.begin(), all.end(), A[i]) - all.begin() + 1;
for (int i = 1; i <= M; ++ i)
if (operation[i].type == 1)
operation[i].x = std::lower_bound(all.begin(), all.end(), operation[i].x) - all.begin() + 1;
}
void prework()
{
dataPreprocess();
ChthollyTree::init();
int &nodeCnt = CDQDivide::nodeCnt;
CDQDivide::Node *node = CDQDivide::node;
// 初始就有的点,应该算进 CDQ 的修改中
for (int i = 1; i <= N; ++ i)
node[ ++ nodeCnt] = CDQDivide::Node(1, 0, i, pre[i], 1);
// 考虑对于每个操作
for (int i = 1; i <= M; ++ i)
if (operation[i].type == 1)
{
int l = operation[i].l, r = operation[i].r, x = operation[i].x;
ChthollyTree::modifyAssign(i, l, r, x);
}
else
{
int l = operation[i].l, r = operation[i].r;
node[ ++ nodeCnt] = CDQDivide::Node(2, i, r, l - 1, 1);
node[ ++ nodeCnt] = CDQDivide::Node(2, i, l - 1, l - 1, -1);
}
}
}
int main()
{
freopen("IceAge.in", "r", stdin);
freopen("IceAge.out", "w", stdout);
Prework::prework();
CDQDivide::CDQ(1, CDQDivide::nodeCnt);
for (int i = 1; i <= M; ++ i)
if (Prework::operation[i].type == 2)
printf("%d\n", ans[i]);
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...