前言


听说是线段树离线查询??

做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线、在线操作。

这题赛后看代码发现有人用的树状数组,$tql$。当然能用树状数组写的线段树也能写,最重要的还是思维上面。

我当时是怎么想来着。一看异或和前缀和不是很像么,我先把数组中所有数字连续异或并存起来,就像处理前缀和一样的。之后对于每组查询,我只要找到区间中相等的数就可以了,然后再取这些数中相隔最近的距离输出即可。想法很好,但是现实很骨感,这样一来每个区间都这样处理不就超时了么,遂放弃。

题意


给出一段长度为$n$的区间,$q$次询问求$L\sim R$这个区间内最短的一段区间$l\sim r$使得$\oplus_{i=l}^{r} a_j= 0$其中$L\leq l<r\leq r$

分析


首先预处理出对于每个位置$i$找到左边离$i$最近的位置$j$使得$a[j] \wedge a[j+1] \wedge a[j+2]\wedge  …a[i]=0$,并记作$pre[i]$。

将询问按$r$从小到大排序,然后从$1\sim n$处理每个位置,对于位置$i$,在线段树上$pre[i]$更新为$i-pre[i]+1$($i$与离$i$右边最近满足$\oplus_{i=l}^{r} a_j= 0$的$r$间的距离),然后查询$(Q[i].l, Q[i].r)$的最小值即可 $[link]$

Code

#include <cstdio>
#include <algorithm>
#define lson rt<<1, l , mid
#define rson rt<<1|1, mid+1 , r
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 5e5+6;
int n, q;
int pos[maxn<<2], pre[maxn], tree[maxn<<2], ans[maxn];
struct node{
int l,r,id;
bool operator<(const node x)const{
return r<x.r;
}
}Q[maxn];
void push_up(int rt){
tree[rt] = min(tree[rt<<1], tree[rt<<1|1]);
}
void update(int rt,int l,int r,int pos,int val){
if(l==r){
tree[rt] = min(tree[rt], val);
return;
}
int mid = (l+r)>>1;
if(pos<=mid) update(lson, pos, val);
else update(rson, pos, val);
push_up(rt);
}
int query(int rt, int l, int r, int ul, int ur){
if(ul<=l&&r<=ur) return tree[rt];
int mid = (l+r)>>1, ans = INF;
if(ur<=mid) return query(lson, ul, ur);
else if(ul>mid) return query(rson, ul, ur);
else return min(query(lson, ul, ur),query(rson, ul, ur));
}
/*这种写法也可以,但是就我以前做过的一道题目来说上面那种更快(不知道为啥,还有待考证)
int query(int rt, int l, int r, int ul, int ur){
if(ul<=l&&r<=ur) return tree[rt];
int mid = (l+r)>>1, ans = INF;
if(ul<=mid) ans = min(ans, query(lson, ul, ur));
if(ur>mid) ans = min(ans, query(rson, ul, ur));
return ans;
}
*/
int main(){
scanf("%d%d", &n, &q);
for(int i = 1;i <= 4*500000; i++){
pos[i] = -1;
tree[i] = INF;
}
int sum = 0; pos[0] = 0;
for(int i = 1,x; i <= n; i++){
scanf("%d",&x);
sum ^= x;
if(pos[sum]!=-1) pre[i] = pos[sum]+1;
else pre[i] = -1;
pos[sum] = i;
}
for(int i = 1; i <= q; i++){
scanf("%d%d", &Q[i].l, &Q[i].r);
Q[i].id = i;
}
sort(Q+1, Q+1+q);
int cnt = 1;
for(int i = 1; i <= n; i++){
if(pre[i]!=-1) update(1, 1, n, pre[i], i-pre[i]+1);
while(Q[cnt].r==i){
ans[Q[cnt].id] = query(1, 1, n, Q[cnt].l, Q[cnt].r);
cnt++;
}
}
for(int i = 1; i <= q; i++){
printf("%d\n", ans[i]==INF?-1:ans[i]);
}
return 0;
}

思考


说实话现在也只是知道了这题这么做是对的,但是自己很难会想到这个方法,可能要多做些题目才知道吧,据说和HH的项链很像,有时间就去看下这题。

还有就是我看这题代码的时候有个想法就是,能不能把$update(1, 1, n, pre[i], i-pre[i]+1)$换成$update(1, 1, n, i, i-pre[i]+1)$。当时觉得这样应该是差不多的,然而$WA$。

仔细想想后,发现用$pre[i]$的位置记录线段长度是有原因的,并非$pre[i]$和$i$都可以。如果用$pre[i]$也即是左端点记录线段长度的话,对于每组查询而言,区间内每个满足条件的点,它所代表的线段的右端点都不会超过当前的$r$,因此可以用来直接求最小值。但是!!假如是用$i$也即是右端点来记录线段长度的话,区间内每个满足条件的点,它所代表的线段的左端点都可能会超过当前的$l$,那个点就不能用来求最小值,但很显然计算的时候会把这个点计入,所以这样得到的结果可能就是错的!!


参考博客:

https://www.cnblogs.com/zjl192628928/p/11661714.html

牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)的更多相关文章

  1. 牛客练习赛53 E 老瞎眼 pk 小鲜肉 (线段树,思维)

    链接:https://ac.nowcoder.com/acm/contest/1114/E来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...

  2. 牛客练习赛53 (E 老瞎眼 pk 小鲜肉) 线段树+离线

    考试的时候切的,类似HH的项链~ code: #include <bits/stdc++.h> #define ll long long #define M 500003 #define ...

  3. 牛客练习赛53 D 德育分博弈政治课 (思维建图,最大流)

    牛客练习赛53 D德育分博弈政治课 链接:https://ac.nowcoder.com/acm/contest/1114/D来源:牛客网 题目描述 德育分学长最近玩起了骰子.他玩的骰子不同,他的骰子 ...

  4. 牛客练习赛53 A 超越学姐爱字符串 (DP)

    牛客练习赛53 超越学姐爱字符串 链接:https://ac.nowcoder.com/acm/contest/1114/A来源:牛客网 超越学姐非常喜欢自己的名字,以至于英文字母她只喜欢" ...

  5. 牛客练习赛53 A-E

    牛客联系赛53 A-E 题目链接:Link A 超越学姐爱字符串 题意: 长度为N的字符串,只能有C,Y字符,且字符串中不能连续出现 C. 思路: 其实就是DP,\(Dp[i][c]\) 表示长度为 ...

  6. 牛客练习赛44 B:小y的线段

    链接:https://ac.nowcoder.com/acm/contest/634/B 来源:牛客网 题目描述 给出\(n\)条线段,第\(i\)条线段的长度为\(a_i\),每次可以从第\(i\) ...

  7. 【牛客练习赛53】A-超越学姐爱字符串

    // 题目地址:https://ac.nowcoder.com/acm/contest/1114/A /* 找规律(碰运气) n:1 = 2 n:2 = 3 n:3 = 5 n:4 = 8 ... d ...

  8. 牛客练习赛53 B 美味果冻

    链接:https://ac.nowcoder.com/acm/contest/1114/B来源:牛客 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言10485 ...

  9. 牛客练习赛33 D tokitsukaze and Inverse Number (树状数组求逆序对,结论)

    链接:https://ac.nowcoder.com/acm/contest/308/D 来源:牛客网 tokitsukaze and Inverse Number 时间限制:C/C++ 1秒,其他语 ...

随机推荐

  1. day119:MoFang:宠物的状态改动&宠物粮道具的使用&宠物死亡处理

    目录 1.宠物的状态改动 2.宠物粮道具的使用 3.宠物死亡处理 1.宠物的状态改动 1.在setting表中为每个宠物配置生命周期时间 因为宠物有多个,每个宠物会有不同的初始生命的饥饿时间,所以我们 ...

  2. Java 中 Executors.newSingleThreadExecutor() 与Executors.newFixedThreadPool(1)有什么区别

    在研究Executors提供的线程池时自然会想到标题这个问题,既然已经有了newFixedThreadPool,为什么还要存在newSingleThreadExecutor这个方法.难道newFixe ...

  3. 意想不到,这个神奇的bug让我加班到深夜

    给大家分享一个近期解决的线上问题,起因是这样的,近期参与公司的一个项目,工程量很大,代码编写测试过后终于到了紧张的上线时刻. 项目上线 上线前照例忐忑不安了一番,因为工程量比较大,预估可能不会很顺利, ...

  4. ASP.NET Core 3.1 中间件

    参考微软官方文档 : https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1 ...

  5. Vue.nextTick()的使用

    什么是Vue.nextTick()?? 定义:在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的 DOM. 所以就衍生出了这个获取更新后的DOM的Vue方法.所 ...

  6. spring cloud gateway 自定义GatewayFilterFactory

    spring cloud gateway提供了很多内置的过滤器,那么因为需求的关系,需要自定义实现,并且要可配置,在一番折腾之后,总算是解决了,那么久记录下来 对于自定义的factory,我们可以选择 ...

  7. qmake奇淫技巧之字符串宏定义

    阅读本文大概需要3.3分钟 我们平时在软件开发过程中需要定义一些宏,以便在代码中调用,这样每次不需要修改代码,只需要修改外部编译命令就可以得到想要的参数,非常方便 比如我们想在软件介绍中显示软件版本, ...

  8. 原生工程接入Flutter实现混编

    前言 上半年我定的OKR目标是帮助团队将App切入Flutter,实现统一技术栈,变革成多端融合开发模式.Flutter目前是跨平台方案中最有潜力实现我们这个目标的,不管是Hybird还是React ...

  9. 【Linux】linux rinetd 端口转发部署

    linux下简单好用的工具rinetd,实现端口映射/转发/重定向 Rinetd是为在一个Unix和Linux操作系统中为重定向传输控制协议(TCP)连接的一个工具.Rinetd是单一过程的服务器,它 ...

  10. Cloudera Manager添加主机节点

    为了监控方便,想把研发环境中的主机节点都纳入Cloudera Manager的管理中,这样在遇到问题时可方便的查看主机的硬件资源情况. 添加主机节点有多种方式,由于我是离线工作,所以选择rpm包的方式 ...