BZOJ 2124等差子序列 线段树&&hash
给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len>=3),使得 Ap1,Ap2,Ap3,…ApLen 是一个等差序列。
输入的第一行包含一个整数 T,表示组数。
下接 T 组数据,每组第一行一个整数 N,每组第二行为一个 1 到 N 的排列, 数字两两之间用空格隔开。
对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一 行“N”。
2
3
1 3 2
3
3 2 1
N
Y
对于5%的数据,N<=100,对于30%的数据,N<=1000,对于100%的数据,N<=10000,T<=7
【解题思路】
首先声明,此题开始并没有什么思路,只找到一个O(N^2)的算法,然而这并没有什么卵用。
老师明示暗示我要我用线段树去做,我苦思冥想没有想出来,于是就抄了题解。
题解是这样的,枚举等差中项,用一颗线段树去维护那些值选了,那些值没选,构成一个01串之后求一个哈希值。
如果出现中项左边的hash值和右边的hash值不一样的情况,就说明存在等差数列,因为证明有一个值在中项左边已经选过,并且与其对应的值在中项右边还没有选。
插入O(logn),查询O(logn),扫一遍O(n)整体O(ologn);
代码略丑
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- using namespace std;
- const int maxn=+, mod=;
- int xp[maxn],a[maxn],n,v,t;
- long long sumv[*maxn][];
- //sumv[i][0] 代表从左边扫的值,sumv[i][1]代表从右边扫的值
- void updata(int u,int l,int r){
- int lc=u<<,rc=lc+;
- if (l==r) sumv[u][]=sumv[u][]=;
- else{
- int mid=(l+r)/;
- if (v<=mid) updata(lc,l,mid);
- else updata(rc,mid+,r);
- sumv[u][]=(sumv[rc][]+xp[r-mid]*sumv[lc][]%mod)%mod;
- sumv[u][]=(sumv[lc][]+xp[mid-l+]*sumv[rc][]%mod)%mod;
- }
- }
- long long query(int node,int l,int r,int a,int b,int x){
- int lc=node<<,rc=lc+;
- if (l==a&&r==b) return sumv[node][x];
- int mid=(l+r)/;
- long long left=,right=;
- if (mid<b) right=query(rc,mid+,r,max(mid+,a),b,x);
- if (a<=mid) left=query(lc,l,mid,a,min(mid,b),x);
- return (x?left+right*xp[max(,mid-a+)]%mod:right+left*xp[max(,b-mid)]%mod)%mod;
- }
- int main(){
- scanf("%d",&t);
- for (int ii=;ii<t;ii++){
- memset(sumv,,sizeof(sumv));
- bool flag=;
- scanf("%d",&n);
- xp[]=;
- for (int i=;i<=n+;i++) xp[i]=(xp[i-]<<)%mod;
- for (int i=;i<n;i++)scanf("%d",&a[i]);
- for (int i=;i<n;i++){
- int x=a[i];
- int len=min(x-,n-x);//长度取短之后比较
- if (len) {
- int t1=query(,,n,x+,x+len,);
- int t2=query(,,n,x-len,x-,);
- if (t1!=t2){
- flag=;
- break;
- }
- }
- v=x;
- updata(,,n);
- }
- if (flag) printf("Y\n");
- else printf("N\n");
- }
- }
以上为堆状线段树,由于我一直喜欢用结构体,所以就又打了一个,然后发现内存时间代码复杂度都比堆要差,大概是因为要建树和结构体太大的缘故。线段树的种类的确要视题目而定。
- #include<cstdio>
- #include<iostream>
- #include<cstring>
- using namespace std;
- const int maxn=+,mod=;
- struct tree{
- int l,r,lch,rch;
- long long sum;
- }tr[maxn*][];
- //tr[now][0]代表从左往右, tr[now][1]代表从右往左
- int cnt,n,t,xp[maxn],a[maxn];
- void build(int now,int l,int r){
- cnt++;
- tr[cnt][].l=tr[cnt][].l=l; tr[cnt][].r=tr[cnt][].r=r;
- if (l==r) return;
- tr[cnt][].lch=tr[cnt][].lch=cnt+;
- int mid=(l+r)>>;
- build(cnt+,l,mid);
- tr[now][].rch=tr[now][].rch=cnt+;
- build(cnt+,mid+,r);
- }
- long long query(int now,int l,int r,int x){
- long long t1=,t2=;
- if (tr[now][x].l==l&&tr[now][x].r==r) return tr[now][x].sum;
- int mid=(tr[now][x].l+tr[now][x].r)>>;
- if (l<=mid) t1=query(tr[now][x].lch,l,min(r,mid),x)%mod;
- if (r>mid) t2=query(tr[now][x].rch,max(mid+,l),r,x)%mod;
- if (x==) return ((t1*xp[max(,r-mid)])%mod+t2)%mod;
- if (x==) return ((t2*xp[max(mid-l+,)])%mod+t1)%mod;
- //返回值的时候*xp的时候错过,乘的是数目,虽然我不知道我刚开始为什么写的不对
- }
- void insert(int now,int x){
- if (tr[now][].l==x&&tr[now][].r==x){
- tr[now][].sum=tr[now][].sum=;
- return;
- }
- int mid=(tr[now][].l+tr[now][].r)>>;
- if (x<=mid) insert(tr[now][].lch,x);
- if (x>=mid+) insert(tr[now][].rch,x);
- int l=tr[now][].l,r=tr[now][].r;
- tr[now][].sum=((tr[tr[now][].lch][].sum*xp[r-mid])%mod
- +tr[tr[now][].rch][].sum)%mod;
- tr[now][].sum=((tr[tr[now][].rch][].sum*xp[mid-l+])%mod
- +tr[tr[now][].lch][].sum)%mod;
- }
- int main(){
- scanf("%d",&t);
- while (t--){
- memset(tr,,sizeof(tr));
- cnt=;//开始忘记清零CE了
- scanf("%d",&n);
- xp[]=;
- bool flag=;
- for (int i=;i<=n+;i++) xp[i]=(xp[i-]<<)%mod;//预处理出所有二的幂
- build(,,n);
- for (int i=;i<n;i++) scanf("%d",&a[i]);
- for (int i=;i<n;i++){
- int x=a[i];
- int len=min(a[i]-,n-a[i]);
- if (len&&query(,x-len,x-,)!=query(,x+,x+len,)){
- flag=;
- break;
- }
- insert(,x);
- }
- if (flag) printf("Y\n");
- else printf("N\n");
- }
- }
BZOJ 2124等差子序列 线段树&&hash的更多相关文章
- bzoj 2124 等差子序列 (线段树维护hash)
2124: 等差子序列 Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 1922 Solved: 714[Submit][Status][Discuss ...
- BZOJ 2124: 等差子序列 线段树维护hash
2124: 等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一 ...
- bzoj2124: 等差子序列线段树+hash
bzoj2124: 等差子序列线段树+hash 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2124 思路 找大于3的等差数列其实就是找等于 ...
- BZOJ2124:等差子序列(线段树,hash)
Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得A ...
- CF452F等差子序列 & 线段树+hash查询区间是否为回文串
记录一下一个新学的线段树基础trick(真就小学生trick呗) 给你一个1到n的排列,你需要判断该排列内部是否存在一个3个元素的子序列(可以不连续),使得这个子序列是等差序列.\(n\) <= ...
- BZOJ 2124: 等差子序列
Sol 线段树+Hash. 首先暴力 等差子序列至少3项就可以了,就枚举中项,枚举公差就可以了,只需要一个数在中项前出现,另一个数在中项前没出现过就可以了.复杂度 \(O(n^2)\) 然后我想了一个 ...
- bzoj 2124 等差子序列 树状数组维护hash+回文串
等差子序列 Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 1919 Solved: 713[Submit][Status][Discuss] Desc ...
- [bzoj2124]等差子序列——线段树+字符串哈希
题目大意 给一个1到N的排列\(A_i\),询问是否存在\(p_i\),\(i>=3\),使得\(A_{p_1}, A_{p_2}, ... ,A_{p_len}\)是一个等差序列. 题解 显然 ...
- bzoj 3207 可持久化线段树+hash
这道题要看出来这个做法还是比较容易说一下细节 1.因为要用hash的区间值域来建树,而hash为了不冲突要开的很大,所以值域就会比较的大,不过这道题好的一点是没有修改,所以直接离散一下就会小很多 2. ...
随机推荐
- 利用JS_SDK实现QQ第三方登录
前言 现如今,第三方登录已成为大部分网站必备的一项基础技能,引入时髦的第三方登录不仅能帮你吸引更多的用户,也让你的网站可以充分利用其他大型网站的用户资源.本次教程将让你的网站最快捷便利地引入QQ登录. ...
- (转)CentOS 6.5下Redis安装详细步骤
Redis简介:Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作 ...
- 让ubuntu使用root帐号并让winscp以root身份登录
ubuntu 服务器默认的root账号是没有激活的,需要用初装的用户账号给root设置管理密码: $ sudo passwd root //用sudo修改root帐户 Password: //输入密 ...
- CSS属性[text-overflow]使用问题
text-overflow:clip | ellipsis 这个属性使用必须通过几个属性一块才能使用 1,overflow:hidden; 这个属性是内容区装不下内容应该怎么办.这里让溢出内容直接不显 ...
- 读jQuery官方文档:样式
样式 使用jQuery,无论是设置或者获取元素样式都十分简便. // 支持驼峰式和分割线式,两种方式等价(原生JavaScript只支持驼峰式) $('h1').css('fontSize'); $( ...
- js 获取url中的查询字符串
function getUrlParam(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)( ...
- SQLSERVER2000使用TSQL将数据导入ACCESS并压缩生成rar
查询分析器操作ACCESS数据表数据 (1)查询:select top 10 * from OPENROWSET('Microsoft.Jet.OLEDB.4.0', 'C:\Documents an ...
- ASP.NET 使用C#代码设置页面元素中的样式或属性
在HTML元素的属性中加上runat ="server"和ID="MyTag"即可在后台代码中通过设置MyTag.Style的值来控制样式. 例如:在前端页面加 ...
- 02线性表链式存储_LinkList--(线性表)
#include "stdio.h" #include "string.h" #include "ctype.h" #include &qu ...
- 05_XML的解析_02_dom4j 解析将信息封装到对象中
[person.xml]要解析的内容 <?xml version="1.0" encoding="UTF-8"?> <students> ...