bzoj2124 等差子序列(hash+线段树)
来源:互联网 发布:应用程序的端口号干什 编辑:程序博客网 时间:2024/05/17 03:30
2124: 等差子序列
Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 719 Solved: 261
[Submit][Status][Discuss]
Description
给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。
Input
输入的第一行包含一个整数T,表示组数。下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开。
Output
对于每组数据,如果存在一个等差子序列,则输出一行“Y”,否则输出一行“N”。
Sample Input
2
3
1 3 2
3
3 2 1
3
1 3 2
3
3 2 1
Sample Output
N
Y
Y
HINT
对于100%的数据,N<=10000,T<=7
Source
【思路】
转化+hash+线段树。
首先需要明确的一点:A是一个1..n的排列。
其次将出现情况统计为01字符串分别表示该数字目前为止是否出现,因此对于一个数字当前没有出现以后一定会出现。例如对于{5,2,1,4,3,6}且已经扫到了4,则有01状态为110010,可以看出如果有一对数字以4为中心分别为01则一定有等差数列。又因为非0即1的性质,所以问题可以转化为两个字串是否相等的问题,对应到例子中即s(2,3)是否等于s(6,5),如果相等则必无等差数列反之则必有一个或多个等差数列。
线段树维护hash,[区间查询单点修改],O(logn)的查询时间,O(logn)的维护时间,总时间为O(nlogn)。
注:求Hash对应一个区间查询。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 5 using namespace std; 6 7 typedef long long LL; 8 const int maxn = 10000+10; 9 const int MOD = 100000007;10 11 int read() {12 char c=getchar();13 while(!isdigit(c)) c=getchar();14 int x=0;15 while(isdigit(c)) {16 x=x*10+c-'0';17 c=getchar();18 }19 return x;20 }21 22 int n;23 int a[maxn],xp[maxn];24 25 LL sumv[4*maxn][2];26 int v;27 void update(int u,int L,int R) {28 int lc=u<<1,rc=lc+1;29 if(L==R) {30 sumv[u][0]=sumv[u][1]=1;31 }32 else {33 int M=L+(R-L)/2;34 if(v<=M) update(lc,L,M);35 else update(rc,M+1,R);36 sumv[u][0]=(sumv[rc][0]+xp[R-M]*sumv[lc][0]%MOD)%MOD;37 sumv[u][1]=(sumv[lc][1]+xp[M-L+1]*sumv[rc][1]%MOD)%MOD;38 }39 }40 LL query(int node,int l,int r,int a,int b,int x){41 int lc=node<<1,rc=lc+1;42 if(l==a&&r==b)return sumv[node][x];43 int m=(l+r)>>1;44 LL left=0,right=0;45 if(m<b)right=query(rc,m+1,r,max(m+1,a),b,x);46 if(a<=m)left=query(lc,l,m,a,min(m,b),x);47 return (x?left+right*xp[max(0,m-a+1)]%MOD:right+left*xp[max(0,b-m)]%MOD)%MOD;48 }49 int main()50 {51 freopen("cin.in","r",stdin);52 freopen("coutme.out","w",stdout);53 int T;54 T=read();55 while(T--) {56 memset(sumv,0,sizeof(sumv));57 n=read();58 xp[0]=1; FOR(i,1,n+5) xp[i]=(xp[i-1]<<1)%MOD;59 FOR(i,1,n) a[i]=read();60 bool f=0;61 FOR(i,1,n) {62 int x=a[i];63 LL lf,rf;64 int len=min(x-1,n-x);65 if(len&&query(1,1,n,x-len,x-1,0)!=query(1,1,n,x+1,x+len,1)){66 f=1;67 break;68 }69 v=x;70 update(1,1,n);71 }72 if(f) printf("Y\n");73 else printf("N\n");74 }75 return 0;76 }
0 0
- bzoj2124 等差子序列(hash+线段树)
- 【bzoj2124】等差子序列 权值线段树维护hash
- [线段树] [Hash] [BZOJ2124] 等差子数列
- bzoj2124 等差子序列 (树状数组 维护hash值)
- bzoj2124 等差子序列
- BZOJ2124 等差子序列
- BZOJ2124: 等差子序列
- 2124: 等差子序列 线段树+hash
- bzoj2124 等差子序列【暴力】
- bzoj 2124: 等差子序列 (线段树+hash)
- BZOJ 2124 等差子序列 线段树维护hash值
- BZOJ 2124 等差子序列 (树状数组 hash)
- 2124: 等差子序列|线段树维护哈希值
- [BZOJ 2124] 等差子序列 Hash+树状数组(附粗略证明)
- bzoj 2124: 等差子序列 树状数组&hash
- [BZOJ]2124 等差子序列 Hash&树状数组
- BZOJ 2124: 等差子序列 [树状数组][hash]
- 最长等差子序列
- Ubuntu 14.04 文件服务器--samba的安装和配置
- bzoj3192 [JLOI2013]删除物品
- 1018. 锤子剪刀布
- bzoj1227 [SDOI2009]虔诚的墓主人(组合公式+离散化+线段树)
- 设计Qt风格的C++API
- bzoj2124 等差子序列(hash+线段树)
- 递归求最大公约数
- HDU1251 统计难题(Trie)
- HDU1247 Hat’s Words(Trie的动态内存版本)
- HDU4099 Revenge of Fibonacci(高精度+Trie)
- HDU2222 Keywords Search(AC自动机)
- 1019. 数字黑洞
- Android知识库
- poj1743 Musical Theme(后缀数组|后缀自动机)