题意

一个长度为n的排列a,\(\forall i\in [1,n] ,1\le a_i \le n\) , m次操作,每次操作:

  1. (1,pos),把 \(a_{pos}\) 变为\(a_{pos} + 10000000\)
  2. (2,r,k) ,找到最小的一个值x,使得\(\forall i\in [1,r], x \neq a_i, x\ge k\)

数据范围:

\(1\le n\le 100000,1\le m\le 100000,1\le r\le n,1\le k\le n\)

分析

  1. 观察每个数的值域,都在\([1,n]\) 之间,而k的范围也在\([1,n]\) 之间,所以答案最终只会在\([1,n+1]\) 之间。

  2. 操作1会使一个数字\(a_i\)加1e7,而这个数已经远远超过n和k,所以也就代表着\(a_i\)从原序列中被删除了。

  3. 由第一条可以知道,每次查询的答案只会在[k,n+1]上,而序列中的数只会在[1,n](进行过1操作的直接删除,不再考虑)。所以我们可以每次查询序列中有没有出现在\([k,n]\) 的数,并且他们的下标是大于r的。如果之前删除过一个数\(x\),那么就把这个下标变成大于n就可以了, 这样对于\(k\le x\) 的情况,\(x\) 所对应的下标都是大于\(r\) 的(也就是把x作为候选答案)

如何维护查询所需要的东西?权值线段树维护区间权值最大下标

  1. 对于操作1,直接让单点的下标变为n+1
  2. 对于操作2,找被区间[k,n]的包含的结点,对于这些结点,如果左节点的最大下标大于r,则递归左节点,否则看右结点,如果都没有,就返回n+1(代表答案候选为n+1)。而递归到终点时,看单点维护的下标是否大于r,如果大于,就返回单点的权值,否则返回n+1.
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int inf = 0x3f3f3f3f;
int a[N],b[N];
struct SegTree{
int l,r,id;
}t[4*N];
int n,m;
void build(int p,int l,int r){
t[p].l = l;t[p].r = r;
if(l == r){
t[p].id = b[l];
return;
}
int mid = l + r >> 1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].id = max(t[p*2].id,t[p*2+1].id);
}
void change(int p,int x){
if(t[p].l == t[p].r && t[p].l == x){
t[p].id = n+1;return;//删除该数,将维护的下标变为n+1
}
int mid = t[p].l + t[p].r >> 1;
if(x <= mid)change(p*2,x);
else if(x > mid)change(p*2+1,x);
t[p].id = max(t[p*2].id,t[p*2+1].id);
}
int query(int p,int l,int r,int x){
if(t[p].l >= l && t[p].r <= r){//找到被[k,n]完全包含的结点
if(t[p].l == t[p].r){
if(t[p].id > x)
return t[p].l;
return n + 1;
}
if(t[p*2].id > x)return query(p*2,l,r,x);
if(t[p*2+1].id > x)return query(p*2+1,l,r,x);
return n + 1;
}
int mid = t[p].l + t[p].r >> 1;
int res = n+1;
if(mid >= l){
res = query(p*2,l,r,x);
}
if(mid < r){
res = min(res, query(p*2+1,l,r,x));
}
return res;
}
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)b[i] = 0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[a[i]] = i;//因为时排列,每个a[i]都不一样
}
build(1,1,n);
int res = 0;
while(m--){
int op,x,y;
scanf("%d%d",&op,&x);
if(op == 1){
x ^= res;
change(1,a[x]);
}
else{
scanf("%d",&y);x^=res;y^=res;
res = query(1,y,n,x);
printf("%d\n",res);
}
}
}
return 0;
}

HDU-6703 array (线段树)的更多相关文章

  1. 2019年CCPC网络赛 HDU 6703 array【权值线段树】

    题目大意:给出一个n个元素的数组A,A中所有元素都是不重复的[1,n].有两种操作:1.将pos位置的元素+1e72.查询不属于[1,r]中的最小的>=k的值.强制在线. 题解因为数组中的值唯一 ...

  2. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  3. hdu 4288 离线线段树+间隔求和

    Coder Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  4. hdu 3016 dp+线段树

    Man Down Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  5. [Codeforces 266E]More Queries to Array...(线段树+二项式定理)

    [Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...

  6. hdu 6703 array(权值线段树)

    Problem Description You are given an array a1,a2,...,an(∀i∈[1,n],1≤ai≤n). Initially, each element of ...

  7. 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法

    C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...

  8. HDU 5877 dfs+ 线段树(或+树状树组)

    1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au, ...

  9. codeforces 719E E. Sasha and Array(线段树)

    题目链接: E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input sta ...

  10. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

随机推荐

  1. python+sklearn+kaggle机器学习

    python+sklearn+kaggle机器学习 系列教程 0.kaggle 1. 初级线性回归模型机器学习过程 a. 提取数据 b.数据预处理 c.训练模型 d.根据数据预测 e.验证 今天是10 ...

  2. Github美化 添加徽章

    Github美化 添加徽章 0. 前言 1. 准备 2. 开始 a. 打开shields.io b.制作静态徽章 c.制作动态徽章 d. 结果 3.额外 0. 前言 之前看见很多大项目都有很多勋章,比 ...

  3. Linux下的strip命令学习

    strip strip是Linux下的一个命令.可以用于给应用脱衣服,帮助我们抹除一些调试信息.(虽然不知道具体是什么,但是会用就好了) 在嵌入式开发领域用到的应该比较多 首先,先写一个示例看看 // ...

  4. 【剑指 Offer】05.替换空格

    题目描述 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例 1: 输入:s = "We are happy." 输出:"We%20a ...

  5. 【C++】《Effective C++》第二章

    第二章 构造/析构/赋值运算 条款05:了解C++默默编写并调用哪些函数 默认函数 一般情况下,编译器会为类默认合成以下函数:default构造函数.copy构造函数.non-virtual析构函数. ...

  6. 使用nodejs和express搭建http web服务

    目录 简介 使用nodejs搭建HTTP web服务 请求nodejs服务 第三方lib请求post 获取http请求的正文 Express和使用express搭建http web服务 express ...

  7. 【Linux】history用法

    通过history命令可以查看我们在系统中输入过的命令 history命令的一些常用参数 -c  清空内存中命令历史 -d #  删除指定的历史命令,比如 history -d 100 ,就是删除第1 ...

  8. P2986 [USACO10MAR]伟大的奶牛聚集(思维,dp)

    题目描述 Bessie is planning the annual Great Cow Gathering for cows all across the country and, of cours ...

  9. CTF------pwn笔记

    地址:http://pwnable.kr/play.php 题目: 使用MobaXterm连接(当然也可以使用别的软件进行连接,用的顺手就行) 连接成功后所以"ls"命令查看目录 ...

  10. Electron入门Demo之桌面应用计算器笔记(二)

    码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14307996.html 在之前总结了一篇自学笔记,通过之前学习到的方法和知识,完成了 ...