HDOJ 6703 Array
HDOJ 6703 Array
题目
array
*Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3577 Accepted Submission(s): 1323
*Problem Description
You are given an array a1,a2,...,an(∀i∈[1,n],1≤ai≤n). Initially, each element of the array is unique.
Moreover, there are m instructions.
Each instruction is in one of the following two formats:
\1. (1,pos),indicating to change the value of apos to apos+10,000,000;
\2. (2,r,k),indicating to ask the minimum value which is not equal to any ai ( 1≤i≤r ) and **not less ** than k.Please print all results of the instructions in format 2.
Input
The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.
In each test case, there are two integers n(1≤n≤100,000),m(1≤m≤100,000) in the first line, denoting the size of array a and the number of instructions.
In the second line, there are n distinct integers a1,a2,...,an (∀i∈[1,n],1≤ai≤n),denoting the array.
For the following m lines, each line is of format (1,t1) or (2,t2,t3).
The parameters of each instruction are generated by such way :For instructions in format 1 , we defined pos=t1⊕LastAns . (It is promised that 1≤pos≤n)
For instructions in format 2 , we defined r=t2⊕LastAns,k=t3⊕LastAns. (It is promised that 1≤r≤n,1≤k≤n )
(Note that ⊕ means the bitwise XOR operator. )
Before the first instruction of each test case, LastAns is equal to 0 .After each instruction in format 2, LastAns will be changed to the result of that instruction.
(∑n≤510,000,∑m≤510,000 )
Output
For each instruction in format 2, output the answer in one line.
Sample Input
3 5 9 4 3 1 2 5 2 1 1 2 2 2 2 6 7 2 1 3 2 6 3 2 0 4 1 5 2 3 7 2 4 3 10 6 1 2 4 6 3 5 9 10 7 8 2 7 2 1 2 2 0 5 2 11 10 1 3 2 3 2 10 10 9 7 5 3 4 10 6 2 1 8 1 10 2 8 9 1 12 2 15 15 1 12 2 1 3 1 9 1 12 2 2 2 1 9 Sample Output
1 5 2 2 5 6 1 6 7 3 11 10 11 4 8 11 Hint
note:
After the generation procedure ,the instructions of the first test case are :
2 1 1, in format 2 and r=1 , k=1
2 3 3, in format 2 and r=3 , k=3
2 3 2, in format 2 and r=3 , k=2
2 3 1, in format 2 and r=3 , k=1
2 4 1, in format 2 and r=4 , k=1
2 5 1, in format 2 and r=5 , k=1
1 3 , in format 1 and pos=3
2 5 1, in format 2 and r=5 , k=1
2 5 2, in format 2 and r=5 , k=2the instructions of the second test case are :
2 7 2, in format 2 and r=7 , k=2
1 5 , in format 1 and pos=5
2 7 2, in format 2 and r=7 , k=2
2 8 9, in format 2 and r=8 , k=9
1 8 , in format 1 and pos=8
2 8 9, in format 2 and r=8 , k=9the instructions of the third test case are :
1 10 , in format 1 and pos=10
2 8 9 , in format 2 and r=8 , k=9
1 7 , in format 1 and pos=7
2 4 4 , in format 2 and r=4 , k=4
1 8 , in format 1 and pos=8
2 5 7 , in format 2 and r=5 , k=7
1 1 , in format 1 and pos=1
1 4 , in format 1 and pos=4
2 10 10, in format 2 and r=10 , k=10
1 2 , in format 1 and pos=2Source
分析
大概意思是给定一个数组, 有两个操作.
-
OP1: 把数组中的某个位置上的数加上一个很大的值.
-
OP2: 问数组中和前r个数都不一样, 但大于等于k的最小的数是什么.
这是一道非常典型的, 难度不大, 但有非常明显的人工埋坑痕迹的题目.
-
第一坑 数据范围
先看数组a的数据的范围
且另有限制条件数组 中每一个数唯一, 这隐性表示了 是1到n的一个排列 .再看修改和查询两个操作的数值范围, 也都被限制在了
之间. 也就是说, 所有的操作都会是在 上进行的.这些细节暗示了我们可以将这个问题进行简化.
-
第二坑 r/k动态计算
这里的
和 不是直接获得的, 而会根据上一个输出的答案进行异或 得到的.一般这么设计的目的都是为了限制使用离线算法, 但这题这么设计的目的其实是想让计算过程变的很不直观, 让你琢磨不透到底进行的是什么操作.
尽管
和 都需要经 处理后才能得到, 但题目中还是特意让处理后的 和 都落在 之间, 说明 这个限制一定非常重要, 解题的时候非用不可.
-
第三坑 故弄玄虚
再细看OP1, 对数组中的某个数加上 10,000,000 .
这个值其实很有讲究, 首先这个数设计的非常随意, 就像是1后面随便按了几个0, 每个位置上的数都加上这么一个同样的数, 也说明了这个值其实并不重要.
其次, 10,000,000 这个数字太大了, 大过了
和 的最大值. 加上这么一个数之后, 基本上这个数字就走远了, 再结合 和 都被限制在了 之间, OP2中的查询已经管不到它了. 其实就暗示了OP1根本就是一个无用操作, 是为了把人绕晕而专门设计的.
分析完这三个坑之后, 再来看一下这题是怎么解的. 首先, 来分析一下这些操作到底是在做什么.
以数组
OP2的输入: 4,3,1
后找第一个大于等于3的数字, 这里可以找到数字5.
OP2的输入: 4,3,1
后找第一个大于等2的数字, 这里可以找到数字2.
这里的
考虑到数组
设数组
对应数组
现在, OP2就可以表示为在数组
这样我们就可以跳过转换前数组
再来看OP1, 数组
解法
可以将数组
我们从根节点往下递归:
-
限制1: 数组的下标要大于等于
(见代码Line-58). -
限制2: 最终的位置上的值要大于
(见代码Line-62).
OP2的就是满足这两个条件下的数组
但限制2并没有什么规律, 这个递归过程很可能要把下标大于
因此, 还需要两个优化:
- 能在左子树上找到结果, 就不用再到右子树上找 (见代码 Line-54 和 Line-76)
- 对树上的每个结点维护一个值来记录这个节点下的子树中能存在的最大下标是多少. 如果最大的下标都还少于
, 就不用再往下找下去了, 肯定不满足限制2
再看操作1, 我们只需要把数组中的这个位置上值更新成
代码
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cmath> #include <algorithm> using namespace std; const int maxn = 100100; int la = 0; int n,m; int a[maxn]; int rt; int val[maxn<<2]; void tree_init(int l,int r,int root) { // 需要优化 //memset(val,0,sizeof(val)); val[root]=0; if(l==r) return; int m=(l+r)/2; tree_init(l,m,root<<1); tree_init(m+1,r,root<<1|1); } void tree_insert(int l, int r,int root, int pos, int v) { if(l==r) { val[root]=v; return ; } int m = (l+r)/2; if(pos<=m) { tree_insert(l,m,root<<1,pos,v); } else { tree_insert(m+1,r,root<<1|1,pos,v); } // val[root] = max(val[root<<1],val[root<<1|1]); } int query_results; bool tree_query(int l, int r, int root, int KK, int RR) { if(l>query_results) { return true; } if(r<KK) { return false; } if(val[root]<=RR) { return false; } if(l==r) { query_results = min(query_results, l); return true; } int m = (l+r)/2; // l...m bool is_find = false; is_find = tree_query(l,m,root<<1,KK,RR); // m+1, r if(is_find==false) { is_find = tree_query(m+1,r,root<<1|1,KK,RR); } return is_find; } void debug_tree(int l, int r, int root) { printf("%2d: [%d---%d] val: %d\n",root,l,r,val[root]); if(l==r) return ; int m = (l+r)/2; debug_tree(l,m,root<<1); debug_tree(m+1,r,root<<1|1); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); tree_init(1,n+1,1); la = 0; for(int i=0;i<n;i++) { scanf("%d",&a[i]); // a[i] 出现在 第i号 位置 tree_insert(1,n+1,1,a[i],i+1); } /* tree_insert(1,n+1,1,n+1,n+1); debug_tree(1,n+1,1); query_results = n+1; tree_query(1,n+1,1,4,3); printf("find: %d\n",query_results); */ for(int i=0;i<m;i++) { int t, pos, rr, kk; scanf("%d",&t); if(t==1) { scanf("%d",&pos); pos = pos^la; //printf("op1: pos: %d\n",pos); if(a[pos-1]==-1) continue; tree_insert(1,n+1,1,a[pos-1],n+1); a[pos-1]=-1; //debug_tree(1,n+1,1); } else if(t==2) { scanf("%d%d",&rr,&kk); rr = rr^la; kk = kk^la; query_results = n+1; tree_query(1,n+1,1,kk,rr); //printf("op2: r: %d k: %d find: %d\n",rr,kk,query_results); la = query_results; printf("%d\n",query_results); } } } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章