题解:P8936 [JRKSJ R7] 月下缭乱
分析
我们可以考虑将每个颜色分开处理,处理出每个颜色需要至少几个操作,使得整个区间被覆盖。
而这个我们可以使用类似时间戳的方法来维护。
如果两个操作都可以覆盖一个点,那我们显然优先用比较靠前的那个。
这启发我们,使用线段树,对于某个点,维护可以操作这个点的最小操作编号。
对于所有点,我们统计这个最小值的最大值,那么所得到的编号就是我们所需要的最大编号(右端点)。
而所有颜色取最大值,就是这个左端点所需的最小右端点。
而显然的,所有比这个右端点大的右端点都是可行的。
代码
因为出题人卡空间,所以使用 new 和 delete 节省空间。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 6;
struct Tree {
int *t;
void init(size_t n) {
t = new int[n * 4]();
}
void modify(int k, int l, int r, int x, int y, int d) {
if(l > y || r < x) return ;
if(x <= l && r <= y) {
t[k] = max(t[k], d);
return ;
}
modify(k << 1, l, (l + r) / 2, x, y, d);
modify(k << 1 | 1, (l + r) / 2 + 1, r, x, y, d);
t[k] = max(t[k], min(t[k << 1], t[k << 1 | 1]));
}
int query(int k, int l, int r, int x, int y) {
if(l > y || r < x) return 0x3f3f3f3f;
if(x <= l && r <= y) {
return t[k];
}
return max(t[k], min(query(k << 1, l, (l + r) / 2, x, y), query(k << 1 | 1, (l + r) / 2 + 1, r, x, y)));
}
~Tree() {
delete[] t;
}
}tree;
int l[N], r[N], x[N];
struct pack {
Tree tree;
vector<int> scc;
};
unordered_map<int, pack> mp;
multiset<unsigned> st;
unsigned sum, X, mul;
inline int read() {
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
x=x*10+ch-'0',ch=getchar();
return x*f;
}
int main() {
ios :: sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
n = read();
m = read();
// cin >> n >> m;
{
tree.init(n);
for(int i = m;i >= 1;i -- ) {
l[i] = read();
r[i] = read();
x[i] = read();
// cin >> l[i] >> r[i] >> x[i];
tree.modify(1, 1, n, l[i], r[i], x[i]);
}
for(int i = 1;i <= n;i ++ ) {
mp[tree.query(1, 1, n, i, i)].scc.push_back(i);
}
}
for(auto &i : mp) {
i.second.tree.init(i.second.scc.size());
if(i.first) {
st.insert(0);
}
}
for(int i = 1;i <= m;i ++ ) {
if(mp[x[i]].scc.size() != 0) {
st.erase(st.find(mp[x[i]].tree.t[1]));
mp[x[i]].tree.modify(1, 1, mp[x[i]].scc.size(), lower_bound(mp[x[i]].scc.begin(), mp[x[i]].scc.end(), l[i]) - mp[x[i]].scc.begin() + 1, upper_bound(mp[x[i]].scc.begin(), mp[x[i]].scc.end(), r[i]) - mp[x[i]].scc.begin() + 1 - 1, i);
st.insert(mp[x[i]].tree.t[1]);
}
sum += *st.begin();
X ^= (*st.begin()) * (m - i + 1);
mul += (*st.begin()) * (m - i + 1);
}
cout << sum << " " << X << " " << mul;
return 0;
}

浙公网安备 33010602011771号