题解:P8936 [JRKSJ R7] 月下缭乱

分析

我们可以考虑将每个颜色分开处理,处理出每个颜色需要至少几个操作,使得整个区间被覆盖。

而这个我们可以使用类似时间戳的方法来维护。

如果两个操作都可以覆盖一个点,那我们显然优先用比较靠前的那个。

这启发我们,使用线段树,对于某个点,维护可以操作这个点的最小操作编号。

对于所有点,我们统计这个最小值的最大值,那么所得到的编号就是我们所需要的最大编号(右端点)。

而所有颜色取最大值,就是这个左端点所需的最小右端点。

而显然的,所有比这个右端点大的右端点都是可行的。

代码

因为出题人卡空间,所以使用 newdelete 节省空间。

#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;
} 
posted @ 2025-09-16 19:45  yanbinmu  阅读(5)  评论(0)    收藏  举报