专栏文章

题解:P8955 「VUSC」Card Tricks

P8955题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mini3pld
此快照首次捕获于
2025/12/02 02:47
3 个月前
此快照最后确认于
2025/12/02 02:47
3 个月前
查看原文
这是一道可癌的毒瘤数据结构题。

前置知识

思路

我们考虑在线段树上二分,线段树维护 11QQ 的修改的异或和,我们遍历每个点,在线段树上二分异或的次数。
那么我们如何才能知道那些修改对那些点有效呢,我们可以创建 nnvector,每个操作其实就是在第 llvector 中加入,在第 r+1r + 1vector 中删除。
时间复杂度 O(nlogn)O(n \log n)

Code

CPP
#include<iostream>
#include<vector>
using namespace std;
const int N = 1e6 + 10;
int n,q,P,dat[N];
vector<pair<int,int> > pos[N];
namespace SegmentTree{
	int sum[N << 2];
	void update(int p,int pos,int val,int l,int r){
		if(l == r){
			sum[p] = val;
			return;
		}
		int mid = (l + r) >> 1;
		if(pos <= mid){
			update(p << 1,pos,val,l,mid);
		}else{
			update(p << 1 | 1,pos,val,mid + 1,r);
		}
		sum[p] = (sum[p << 1] | sum[p << 1 | 1]);
	}
	int query(int p,int l,int r,int k){
		if((sum[p] | k) <= P){
			return -1;
		}
		if(l == r){
			return l;
		}
		int mid = (l + r) >> 1;
		if((sum[p << 1] | k) > P){
			return query(p << 1,l,mid,k);
		}else{
			return query(p << 1 | 1,mid + 1,r,(k | sum[p << 1]));
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> q >> P;
	for(int i = 1;i <= n;i ++){
		cin >> dat[i];
	}
	for(int i = 1;i <= q;i ++){
		int l,r,k;
		cin >> l >> r >> k;
		pos[l].push_back({i,k});
		pos[r + 1].push_back({i,0});
	}
	for(int i = 1;i <= n;i ++){
		for(pair<int,int> p : pos[i]){
			int id = p.first,val = p.second;
			SegmentTree::update(1,id,val,1,q);
		}
		cout << SegmentTree::query(1,1,q,dat[i]) << " ";
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...