HDU6703 权值线段树

题意: 给定一个长度为 n n n的排列 q q q,即 n n n个元素值都属于 1 n 1 \sim n 1n,且 n n n个元素互不相同。
修改操作:将 q [ p o s ] q[pos] q[pos]加上 1 e 7 1e7 1e7。查询操作:找到与 q [ 1 r ] q[1 \sim r] q[1r]都不相同的且不小于 k k k的最小值。

题解: 通过分析可得,查询的答案最大为 n + 1 n+1 n+1,即我们每次只需要从 [ k , n + 1 ] [k,n+1] [k,n+1]中查找答案即可。对于每次修改操作,加上 1 e 7 1e7 1e7相当于在 1 r 1\sim r 1r中删除这个数,所以将其索引置为INF即可。
线段树叶节点表示权值,维护每个区间中最大的索引,二分查询 [ k , n + 1 ] [k,n+1] [k,n+1]这个区间,由于是权值线段树故先查询左子树,再查询右子树。注意题目中 p o s , r , k pos,r,k pos,r,k都要异或上前一次查询的答案。


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 1e5 + 10;
int q[N], pos[N], T, n, m;
int ans;
int op, r, k, pos1;

struct Node{
	int l, r;
	int p;
}tr[N << 2];

void pushup(int u) {
	tr[u].p = max(tr[u << 1].p, tr[u << 1 | 1].p);
}

void build(int u, int l, int r) {
	tr[u] = {l, r, 0};
	if(l == r) {
		tr[u].p = pos[l];
		return ;
	}
	
	int mid = l + r >> 1;
	build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
	pushup(u);
}

void modify(int u, int x) {
	if(tr[u].l == tr[u].r) {
		tr[u].p = n + 1;
		return ;
	}
	
	int mid = tr[u].l + tr[u].r >> 1;
	if(x <= mid) modify(u << 1, x);
	else modify(u << 1 | 1, x);
	pushup(u);
}

void query(int u, int l, int r, int Mpos) {
	if(tr[u].l == tr[u].r) {
		ans = tr[u].l;
		return ;
	}
	
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid && tr[u << 1].p > Mpos) query(u << 1, l, r, Mpos);
	if(ans == -1 && tr[u << 1 | 1].p > Mpos) query(u << 1 | 1, l, r, Mpos); 
}

int main()
{
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &n, &m);
		for(int i = 1; i <= n; i++)
			scanf("%d", &q[i]), pos[q[i]] = i;
		pos[n + 1] = n + 1;
		build(1, 1, n + 1);
		
		ans = 0;
		while(m--) {
			scanf("%d", &op);
			if(op == 1) {
				scanf("%d", &pos1);
				pos1 ^= ans;
				modify(1, q[pos1]);
			}
			
			else {
				scanf("%d%d", &r, &k);
				r ^= ans, k ^= ans;
				ans = -1;
				query(1, k, n + 1, r);
				printf("%d\n", ans);
			}
		}
	}
	return 0;
}
全部评论

相关推荐

10-23 16:33
门头沟学院 Java
本人某中9本科,成绩中等,目前没科研没实习,目前后端学到了javaWeb,开始没定好方向,在学国外课程,走工程路线起步有点晚了,到这个时间点了还在学JavaWeb,顿感迷茫,不知道是坚持走下去还是寒假去准备考研。考研这个路弄得我还是心痒痒的,因为从众考研的人也不在少数,所以会有这方面的心理安慰吧,就是“不行我可以去考研啊”,而且意味着三年的缓冲,为了复试还有积攒经验美化简历,其实现在也可以去申入实验室打杂;就业可能意味着多些工作经验,工程岗应该到后面还是经验大于学历?还是有点迷茫了,求助好心人有无路线启发
千千倩倩:同27给点建议,现在这个时间点可以快速看完外卖和点评,不用跟着敲,但一定要在看的时候总结每个部分的整个业务流程,对其中的实现有一个大概的印象。然后直接开始看八股,刷算法。八股和算法最好还是在项目学习中穿插着看。如果计算机基础,算法这些基础好,加上每天刻苦学习,两周可以达到勉强能面试的水平,到时候就直接海投中小厂,在约面和面试的过程中不断巩固知识。没找到实习也没关系,就当积累经验。再沉淀一波直接明年三月开始投暑期,毕竟是9本,总是有面试机会的,只要你这三个月不懈怠,面试发挥得一定不错,只要拿到一个中,大厂暑期实习,秋招就有竞争力了。总得而言,现在还有机会,但是时间非常紧张,需要你结合自己情况考虑,共勉
你会选择考研还是直接就业
点赞 评论 收藏
分享
09-28 09:18
吉首大学 Java
离上岸不远了的牛油很...:同27,你写的专业技能那些是真熟练了吗,我感觉稍微问深一点我都要🐔
你找实习最大的坎坷是什么
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务