牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)
前言
听说是线段树离线查询??
做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线、在线操作。
这题赛后看代码发现有人用的树状数组,$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小鲜肉(思维+线段树+离线)的更多相关文章
- 牛客练习赛53 E 老瞎眼 pk 小鲜肉 (线段树,思维)
链接:https://ac.nowcoder.com/acm/contest/1114/E来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...
- 牛客练习赛53 (E 老瞎眼 pk 小鲜肉) 线段树+离线
考试的时候切的,类似HH的项链~ code: #include <bits/stdc++.h> #define ll long long #define M 500003 #define ...
- 牛客练习赛53 D 德育分博弈政治课 (思维建图,最大流)
牛客练习赛53 D德育分博弈政治课 链接:https://ac.nowcoder.com/acm/contest/1114/D来源:牛客网 题目描述 德育分学长最近玩起了骰子.他玩的骰子不同,他的骰子 ...
- 牛客练习赛53 A 超越学姐爱字符串 (DP)
牛客练习赛53 超越学姐爱字符串 链接:https://ac.nowcoder.com/acm/contest/1114/A来源:牛客网 超越学姐非常喜欢自己的名字,以至于英文字母她只喜欢" ...
- 牛客练习赛53 A-E
牛客联系赛53 A-E 题目链接:Link A 超越学姐爱字符串 题意: 长度为N的字符串,只能有C,Y字符,且字符串中不能连续出现 C. 思路: 其实就是DP,\(Dp[i][c]\) 表示长度为 ...
- 牛客练习赛44 B:小y的线段
链接:https://ac.nowcoder.com/acm/contest/634/B 来源:牛客网 题目描述 给出\(n\)条线段,第\(i\)条线段的长度为\(a_i\),每次可以从第\(i\) ...
- 【牛客练习赛53】A-超越学姐爱字符串
// 题目地址:https://ac.nowcoder.com/acm/contest/1114/A /* 找规律(碰运气) n:1 = 2 n:2 = 3 n:3 = 5 n:4 = 8 ... d ...
- 牛客练习赛53 B 美味果冻
链接:https://ac.nowcoder.com/acm/contest/1114/B来源:牛客 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言10485 ...
- 牛客练习赛33 D tokitsukaze and Inverse Number (树状数组求逆序对,结论)
链接:https://ac.nowcoder.com/acm/contest/308/D 来源:牛客网 tokitsukaze and Inverse Number 时间限制:C/C++ 1秒,其他语 ...
随机推荐
- 项目实战--解决运行sql文件错误
说明: 新项目启动,通过公司运维同学给的数据库脚本在Navicat中建项目的数据库,运行脚本时报错 Error Code: 1227. Access denied; you need (at leas ...
- spark知识点_RDD
来自官网的Spark Programming Guide,包括个人理解的东西. 这里有一个疑惑点,pyspark是否支持Python内置函数(list.tuple.dictionary相关操作)?思考 ...
- Zap简单使用
前言 zap 是 uber 开源的一个日志记录的包, uber 在 go 的领域建树颇多, zap 更是优秀, 相比于自带的 log ,他有更多的功能, 当然, 最显眼的还是他很快, 本文介绍 zap ...
- Typora笔记上传到播客时图片不显示问题解决(已解决)
前言: 相信我们都遇到过,使用Typora做笔记是一件非常令人舒服的事,然而,它却有一个非常难受的地方,那就是我们在做完笔记想要将其上传到自己的博客时,复制粘贴的图片无法显示.因为Typora复制 ...
- LeetCode 371两数之和
题目描述: 不使用运算符 + 和 - ,计算两整数 a .b 之和. 思路: 既然不能使用运算符操作就要考虑到,位运算的加法. 加法有进位的时候和不进位的时候 ...
- 【SpringBoot】Spring Boot,开发社区讨论交流网站首页。
初识Spring Boot,开发社区讨论交流网站首页. 文章目录 初识Spring Boot,开发社区讨论交流网站首页. 1.项目简介 2. 搭建开发环境 JDK Apache Maven Intel ...
- kubernets之服务发现
一 服务与pod的发现 1.1 服务发现pod是很显而易见的事情,通过简称pod的标签是否和服务的标签一致即可,但是pod是如何发现服务的呢?这个问题其实感觉比较多余,但是接下来你就可能不这么想了 ...
- LeetCode589. N叉树的前序遍历
题目 法一.递归 1 class Solution { 2 public: 3 vector<int>ans; 4 void dfs(Node* root){ 5 if(root!=NUL ...
- XSS类型,防御及常见payload构造总结
什么是XSS? XSS全称是Cross Site Scripting即跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了. 最直接的例子:&l ...
- Ubuntu安装Vivado
Step1 安装必要的库文件: sudo apt install libncurses5 build-essential openjdk-11-jdk Step2 进入vivado的安装文件夹 sud ...