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

题解
因为数组中的值唯一,且在1到n的范围内,而询问的r和k也在1到n的范围内。 所以对于任意一个被操 作1修改过的值都不会成为询问的答案,而询问的结果也必然在k到n+1的范围内。 因为没有被修改过 值是唯一的,所以可以建立权值线段树,维护权值区间内的值所在下标的最大值。而询问则转化为不小 于k的值里面,下标超过r的最小权值是多少。 如何处理询问呢,一种较为暴力的解法是直接在线段树上 询问权值在k到n+1的范围内第一个下标超过r的权值是多少。但复杂度可能会被卡,需要减枝。 再加上 一个额外的判断就可以了,就是在递归查询完左子树内存不存在大于r的下标之后,如果不存在,则先 看一下右子树内的下标的最大值是否大于r。如果不大于r,则不必再进入右子树内查询,否则答案一定 在右子树内。在进左子树之前也利用同样的判断条件来判断是否有必要进入左子树,这样做可以保证单 次查询的复杂度是O(log n) 的。 而对于操作1,则等价于修改某个权值的下标为无穷大。操作复杂度也 是O(log n )的。 综上所述,得到了一个复杂度为O( m * log n )的在线算法,可以较快地通过此题。

/*HDU 6703 array
权值线段树 在线处理
2019/08/27 12:00
*/
#pragma GCC optimize(3,"Ofast","inline") //G++
#pragma comment(linker, "/STACK:102400000,102400000")
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include <functional>
#define TEST freopen("in.txt","r",stdin);
#define mem(a,x) memset(a,x,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ull; // %llu
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod=1e9+;
const int INF = 1e6+;
const int maxn = 1e5+;
int n,q;
struct node
{
int l,r,pos; //建立权值线段树 维护区间下标最大值
} t[*maxn];
int a[maxn];
void build(int l,int r,int o) //一颗大树由此而生
{
t[o].l=l;
t[o].r=r;
if(l==r)
{
return ;
}
int mid=(l+r)>>;
build(l,mid,o<<);
build(mid+,r,o<<|);
}
void pushup(int o) //自如其名 pushup
{
t[o].pos=max(t[o<<].pos,t[o<<|].pos);
}
void add(int o,int x,int pos) //添加操作 维护区间下标最大值
{
if(t[o].l==t[o].r&&t[o].l==x)
{
t[o].pos=pos;
return ;
}
int mid=(t[o].l+t[o].r)>>;
if(x<=mid)
add(o<<,x,pos);
else
add(o<<|,x,pos);
pushup(o);
}
int qurey(int o,int l,int r,int ask)
{
if(t[o].l==t[o].r) //到叶子节点判读答案是否成立
{
if(t[o].pos>ask)
return t[o].l;
else
return INF;
}
if(t[o].l==l&&t[o].r==r) //在当期节点区间时 需要根据左右子树的pos值判读下一步往哪边走(剪枝)
{
if(t[o<<].pos>ask)
{
return qurey(o<<,l,(l+r)>>,ask);
}
else if(t[o<<|].pos>ask)
{
return qurey(o<<|,(l+r)>>|,r,ask);
}
else
return INF;
}
int mid=(t[o].l+t[o].r)>>; //熟悉的操作
if(r<=mid)
{
return qurey(o<<,l,r,ask); //锁定区间
}
else if(l>mid)
{
return qurey(o<<|,l,r,ask); //还是锁定区间
}
else
{
return min(qurey(o<<,l,mid,ask),qurey(o<<|,mid+,r,ask)); //锁定区间 答案即可能在左子树也可能在右子树 所以取左右子树中最小的值(有可能左子树返回INF)
}
}
void init() //输入
{ scanf("%d%d",&n,&q);
build(,+n,);
for(int i=; i<=n; i++)
{
scanf("%d",&a[i]);
add(,a[i],i);
}
add(,n+,INF);
}
void solve() //解决
{
int op,last=; //在线处理
while(q--)
{
scanf("%d",&op);
if(op==)
{
int pos;
scanf("%d",&pos);
pos^=last;
add(,a[pos],INF);
}
else
{
int r,k;
scanf("%d%d",&r,&k);
r^=last,k^=last;
last=qurey(,k,n+,r);
printf("%d\n",last);
}
}
}
int main()
{
// TEST
int T;
scanf("%d",&T);
while(T--)
{
mem(t,);
init();
solve();
}
}

2019年CCPC网络赛 HDU 6703 array【权值线段树】的更多相关文章

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

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

  2. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

  3. 2015合肥网络赛 HDU 5489 Removed Interval LIS+线段树(树状数组)

    HDU 5489 Removed Interval 题意: 求序列中切掉连续的L长度后的最长上升序列 思路: 从前到后求一遍LIS,从后往前求一遍LDS,然后枚举切开的位置i,用线段树维护区间最大值, ...

  4. 2015上海网络赛 HDU 5475 An easy problem 线段树

    题意就不说了 思路:线段树,维护区间乘积.2操作就将要除的点更新为1. #include<iostream> #include<cstdio> #include<cstr ...

  5. Petya and Array (权值线段树+逆序对)

    Petya and Array http://codeforces.com/problemset/problem/1042/D time limit per test 2 seconds memory ...

  6. HDU 6609 离散化+权值线段树

    题意 有一个长度为\(n\)的数组W; 对于每一个\(i\)(\(1<=i<=n\)),你可以选择中任意一些元素W[k] (\(1<=k<i\)),将他们的值改变为0,使得\( ...

  7. ccpc 网络赛 hdu 6155

    # ccpc 网络赛 hdu 6155(矩阵乘法 + 线段树) 题意: 给出 01 串,要么询问某个区间内不同的 01 子序列数量,要么把区间翻转. 叉姐的题解: 先考虑怎么算 \(s_1, s_2, ...

  8. ccpc网赛 hdu6703 array(权值线段树

    http://acm.hdu.edu.cn/showproblem.php?pid=6703 大意:给一个n个元素的数组,其中所有元素都是不重复的[1,n]. 两种操作: 将pos位置元素+1e7 查 ...

  9. HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others)    M ...

随机推荐

  1. MySQL-快速入门(10)触发器

    1.什么是触发器 触发器是与表有关的命名数据库对象.触发器由事件来触发某个操作. 触发器是特殊的存储过程,触发器不需要call语句来调用,也不需要手工启动,只需要确定一个预定义的事件发生的时候,就会被 ...

  2. 万万没想到,Spring Boot 竟然这么耗内存!

    Spring Boot总体来说,搭建还是比较容易的,特别是Spring Cloud全家桶,简称亲民微服务. 但在发展趋势中,容器化技术已经成熟,面对巨耗内存的Spring Boot,小公司表示用不起. ...

  3. The Frog's Games

    The Frog's Games Problem Description The annual Games in frogs' kingdom started again. The most famo ...

  4. C++中的深拷贝和浅拷贝构造函数

    1,对象的构造在实际工程开发当中是相当重要的,C++ 中使用类就要创建对象,这 就涉及了对象的构造,本节课讲解对象的构造和内存操作方面的问题: 2,实际工程开发中,bug 产生的根源,必然的会有内存操 ...

  5. Mysql中explain作用详解

    一.MYSQL的索引 1.索引(Index):帮助Mysql高效获取数据的一种数据结构.用于提高查找效率,可以比作字典.可以简单理解为排好序的快速查找的数据结构.2.索引的作用:便于查询和排序(所以添 ...

  6. virtualenvwrapper安装和使用

    virtualenvwrapper安装和使用步骤: 1.安装: *nix上安装的命令: pip install virtualenvwrapper windows上安装的命令: pip install ...

  7. Django @csrf_exempt不能在类视图中工作(Django @csrf_exempt not working in class View)

    我在Django 1.9中有一个使用SessionMiddleware的应用程序.我想在同一个项目中为这个应用程序创建一个API,但是在做一个POST请求时,它不能使用@csrf_exempt注释. ...

  8. kotlin学习(9)注解

    我们一般使用类和函数要说明类和函数的确切名称.调用一个类,你需要知道它定义在哪个类中,还有它的名称和参数的类型. 注解和反射可以给你超越这个规则的能力,让你编写出使用事先未知的任意类的代码.注解赋予这 ...

  9. 模板 - Floyd

    void Floyd(){ for(int k = 1; k <= n; ++k) { for(int i = 1; i <= n; ++i) { for(int j = 1; j < ...

  10. IWorkspaceFactory pWorkspaceFactory = new ShapefileWorkspaceFactoryClass(); 时,报COMException

    解决办法: 在Program.cs的Main函数中添加如下代码: ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Desktop);