首页 > 其他分享 >NOIP集训 P11071 「QMSOI R1」 Distorted Fate 题解

NOIP集训 P11071 「QMSOI R1」 Distorted Fate 题解

时间:2024-11-09 17:08:23浏览次数:1  
标签:le R1 NOIP int 题解 req pos inf

题解: P11071 「QMSOI R1」 Distorted Fate

给定一个长度为 \(n\) 的数组 \(A\),你需要完成以下 \(q\) 次操作。
1.1 l r x将 \(A_i(l\le i\le r)\) 异或上 \(x\)。
2.2 l r求:

\[(\sum_{i=l}^r\bigcup_{j=l}^iA_j ) \bmod 2^{30} \]

其中 \(\bigcup\) 表示按位或。

Input

第一行输入两个数 \(n\) 和 \(q\),代表数组长度和操作的次数。
第二行输入 \(n\) 个整数,第 \(i\) 个数代表 \(A_i\) 的值。
接下来 \(q\) 行,每行输入三个整数 \(opt,l,r\) 。
若 \(opt=1\) ,则再输入一个整数 \(x\) 表示将区间 \([l,r]\) 中 \(A_i\) 异或上 \(x\)。
若 \(opt=2\) ,则代表这是一次查询。

Output

对于每个查询,输出一行一个整数代表所求式子的值 \(\bmod \ 2^{30}\) 的结果。

Note

对于所有数据,满足 \(0\le a_i,x<2^{30},1\le l\le r\le n\) 。
空间限制 \(100MB\) 。

分析

很自然往拆位的思路去想。
因为空间限制卡的很死,所以不能直接在线做。
先把操作离线下来,每一位单独做。由于是前缀按位或,相当于对于 \([l,r]\) 的 \(0/1\) 序列,找到第一个出现的 \(1\) 的位置,其后包括它本身都会对答案有贡献。
这样就可以考虑线段树上每个节点维护两个值 \(pos_0\) 和 \(pos_1\) ,建树时如果 \(A_i\) 当前处理的位置上为 \(1\) 就把 \(pos_1\) 赋成 \(i\), \(pos_0\) 赋成极大值;当前位置上为 \(0\) 就反过来。每次处理如果 \(x_i\) 这一位为 \(1\) 就可以直接把 \([l,r]\) 的 \(pos_0, pos_1\) 交换(等价于异或),用 \(tag_u\) 延迟下放标记即可。
每一位操作可以重复建在同一棵线段树上。记得清空标记。

AC代码:

#include<bits/stdc++.h>
using namespace std;

inline int read() {
	int f = 1, otto = 0;
	char a = getchar();
	while(!isdigit(a)) {
		if(a == '-') f = -1;
		a = getchar();
	}
	while(isdigit(a)) {
		otto = (otto << 1) + (otto << 3) + (a ^ 48);
		a = getchar();
	}
	return f * otto;
}

const int maxn = 2e5 + 10, mo = 1 << 30, inf = 1 << 30;
int bit, a[maxn], ans[maxn], pos0[maxn << 2], pos1[maxn << 2];
struct REQ{
	int op, l, r, x;
}req[maxn];
bool tag[maxn << 2];

void upd(int u) {
	pos0[u] = min(pos0[u << 1], pos0[u << 1 | 1]), pos1[u] = min(pos1[u << 1], pos1[u << 1 | 1]);
	return;
}

void build(int u, int l, int r) {
	if(l == r) {
		if((a[l] >> bit) & 1) pos0[u] = inf, pos1[u] = l;
		else pos0[u] = l, pos1[u] = inf;
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
	return upd(u), void(0);
}

void pushdown(int u) {
	if(!tag[u]) return;
	swap(pos0[u << 1], pos1[u << 1]), swap(pos0[u << 1 | 1], pos1[u << 1 | 1]);
	tag[u << 1] ^= 1, tag[u << 1 | 1] ^= 1;
	tag[u] = 0; //记得清空tag 
	return;
}

void Do(int u, int l, int r, int ql, int qr) {
	if(ql <= l && r <= qr) {
		tag[u] ^= 1;
		swap(pos0[u], pos1[u]);
		return;
	}
	pushdown(u);
	int mid = l + r >> 1;
	if(ql <= mid) Do(u << 1, l, mid, ql, qr);
	if(mid < qr) Do(u << 1 | 1, mid + 1, r, ql, qr);
	return upd(u), void(0);
}

int ask(int u, int l, int r, int ql, int qr) {
	if(ql <= l && r <= qr) return pos1[u];
	pushdown(u);
	int mid = l + r >> 1, ret = inf;
	if(ql <= mid) ret = min(ret, ask(u << 1, l, mid, ql, qr));
	if(mid < qr) ret = min(ret, ask(u << 1 | 1, mid + 1, r, ql, qr));
	return ret;
} 

int main() {
	int n = read(), q = read();
	for(int i = 1; i <= n; i++) a[i] = read();
	for(int i = 1; i <= q; i++) {
		req[i].op = read(), req[i].l = read(), req[i].r = read();
		if(req[i].op == 1) req[i].x = read();
	}
	
	for(bit = 0; bit <= 30; bit++) {
		memset(tag, 0, sizeof tag); 
		build(1, 1, n);
		for(int i = 1; i <= q; i++) {
			if(req[i].op == 1 && (req[i].x >> bit) & 1) Do(1, 1, n, req[i].l, req[i].r);
			if(req[i].op == 2) {
				int res = ask(1, 1, n, req[i].l, req[i].r);
				if(res != inf) ans[i] = (ans[i] + 1ll * (req[i].r - res + 1) * (1 << bit) % mo) % mo;
			}
		}
	}
	
	for(int i = 1; i <= q; i++) {
		if(req[i].op == 2) printf("%d\n", ans[i]);
	} 
	return 0;
}

标签:le,R1,NOIP,int,题解,req,pos,inf
From: https://www.cnblogs.com/Ydoc770/p/18536838

相关文章

  • [DMY]2024 NOIP 模拟赛 Day 6
    今天状态不太好。赛时T1一看是概率先畏惧三分。拖拖拉拉写完了\(2^n\)的暴力后开始打表找特殊性质的规律。找了一个答案是\(8\over27\)\(=(\frac{2}{3})^3\),其中\(2\over3\)\(=\frac{10}{10+5}\)。然后意识到这个性质的答案是\((\frac{x}{a+x})^{\log_2n}\),快速写......
  • [COCI2022-2023#5] Slastičarnica 题解
    前言题目链接:洛谷。题意简述一个长为\(n\)的序列\(\{a_n\}\)和\(q\)次操作,第\(i\)次操作中,你可以删除序列长为\(d_i\)的前缀或后缀,并需要保证删除的所有数\(\geqs_i\)。每次操作前,你可以选择任意长度的前缀或后缀,并将其删除,也可以不操作。请问,在你不能进行下一次操......
  • CodeforceTon Round 4 div1 + div2 题解
    题解A-EDreamissofar~A.BeautifulSequence检查每一位对应的数字是否小于等于位置,如果可以说明这个数字可以移动到对应位置上,遍历即可#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;voidsolve(){ intn; cin>>n; vector<int>a......
  • CF607B Zuma 题解
    CF607BZuma不知道为什么你谷会评蓝,这不是很基础的区间DP吗。Problem-607B-Codeforces题意简述消除回文子串的最小次数。思路对于区间\([i,j]\),如果它是回文的,那么消除它所需的次数是\(1\)。如果它不是回文的,但是\(a[i]==a[j]\),那么当区间\([i+1,j-1]\)被消除到只剩下......
  • [ARC158C] All Pair Digit Sums 题解
    C-AllPairDigitSums题意:设\(f(x)\)为\(x\)的数字和。例如\(f(158)=1+5+8=14\)。给定一个长度为\(N\)的正整数序列\(A\),求\(\sum_{i=1}^{N}\sum_{j=1}^{N}f(A_i+A_j)\)。分析:首先明确\(f(x)\)为\(x\)的数位和。举例情况:若有两个数分别为:\(12,21\)。\[f(......
  • QT中大量数据存储至excel的问题解决
            因为这个问题困扰了我很久,所以在这里记录一下,顺便给可能会遇到类似问题的人提供一点帮助。        在qt中,如果用C++处理数据保存到excel,正常来说在pro文件中添加axcontainer 然后就能够调用到excel,但是这只能适用于数量级没那么大时的需求。  ......
  • [NOIP2018 提高组] 旅行
    算法对于一棵树的情况,dfs+贪心选取显然是正确的对于基环树的情况我们观察到城市不能重复行走所以长为\(L\)的环最多只会被访问\(L-1\)条边枚举断边,再跑dfs+贪心即可代码#include<bits/stdc++.h>constintMAXN=5e3+20;intn,m;std::vector<int>e......
  • ffmpeg问题解决:Unrecognized option 'preset'. Error splitting the argument list: O
    来到这里,十有八九是手动编译安装的ffmpeg,在跑视频流程序或命令时出现这个问题。跟这个报错:ffmpeg:errorwhileloadingsharedlibraries:libx264.so.164:cannotopensharedobjectfile:Nosuchfileordirectory的错误本质是一样的,都是由于ffmpeg时使用到了libx264,而在......
  • 【NOIP普及组】统计单词数
    【NOIP普及组】统计单词数......
  • 讲座の题解
    讲座配套题单的题解喵每题的文字解释会逐渐补充,如果有疑问直接私信喵目录讲座配套题单的题解喵目录A-看看你会不会用电脑B-求求你不要用内置函数C-GPAD-minE-for循环大神F-居然有人说这个是线性代数G-高三同学秒了H-无穷级数I-不要用内置函数......