BZOJ 2124 (线段树 + hash)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2124
题意:给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列。
题解:显然若存在i < j < k,使得 aj - ai = ak - aj 则答案存在,考虑枚举 j ,判断是否存在 t 使得 aj - t 在 j 的左边且 aj + t 在 j 的右边。 对 n 个点建线段树,如果数 v 在 aj 的左边则线段树第 v 个叶子节点值为 1,否则为 0,枚举 j 的过程中进行单点修改,可以发现枚举到 j 的时候,若不存在长度为 3 的等差数列,则左边倒着和右边正着的 01 序列是完全相同的,故可以用哈希来维护一个区间正着和倒着的值,查询直接判断是否相等即可。(注意细节)
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define mst(a,b) memset((a),(b),sizeof(a)) 6 #define mp(a,b) make_pair(a,b) 7 #define pi acos(-1) 8 #define pii pair<int,int> 9 #define pb push_back 10 const int INF = 0x3f3f3f3f; 11 const double eps = 1e-6; 12 const int MAXN = 1e4 + 10; 13 const int MAXM = 1e3 + 10; 14 const ll mod = 1e9 + 7; 15 16 int a[MAXN]; 17 ll add[MAXN],hash1[MAXN<<2],hash2[MAXN<<2]; 18 19 void pushup(int rt,int l,int r) { 20 int mid = (l + r) >> 1; 21 hash1[rt] = (hash1[rt<<1] * add[r - mid] + hash1[rt<<1|1]) % mod; 22 hash2[rt] = (hash2[rt<<1|1] * add[mid - l + 1] + hash2[rt<<1]) % mod; 23 } 24 25 void update(int rt,int l,int r,int pos) { 26 if(l == r) { 27 hash1[rt] = hash2[rt] = 1; 28 return ; 29 } 30 int mid = (l + r) >> 1; 31 if(pos <= mid) update(rt<<1,l,mid,pos); 32 else update(rt<<1|1,mid + 1,r,pos); 33 pushup(rt,l,r); 34 } 35 36 ll query1(int rt,int l,int r,int ql,int qr) { 37 if(ql > qr) return 0; 38 if(ql == l && qr == r) return hash1[rt]; 39 int mid = (l + r) >> 1; 40 if(qr <= mid) return query1(rt<<1,l,mid,ql,qr); 41 else if(ql > mid) return query1(rt<<1|1,mid + 1,r,ql,qr); 42 else return (query1(rt<<1,l,mid,ql,mid) * add[qr - mid] + query1(rt<<1|1,mid + 1,r,mid + 1,qr)) % mod; 43 } 44 45 ll query2(int rt,int l,int r,int ql,int qr) { 46 if(ql > qr) return 0; 47 if(ql == l && qr == r) return hash2[rt]; 48 int mid = (l + r) >> 1; 49 if(qr <= mid) return query2(rt<<1,l,mid,ql,qr); 50 else if(ql > mid) return query2(rt<<1|1,mid + 1,r,ql,qr); 51 else return (query2(rt<<1|1,mid + 1,r,mid + 1,qr) * add[mid - ql + 1] + query2(rt<<1,l,mid,ql,mid)) % mod; 52 } 53 54 int main() { 55 #ifdef local 56 freopen("data.txt", "r", stdin); 57 // freopen("data.txt", "w", stdout); 58 #endif 59 add[1] = 3; 60 for(int i = 2; i < MAXN; i++) add[i] = add[i - 1] * (ll)3 % mod; 61 int t; 62 scanf("%d",&t); 63 while(t--) { 64 int n; 65 scanf("%d",&n); 66 for(int i = 1; i <= n; i++) scanf("%d",&a[i]); 67 mst(hash1, 0); 68 mst(hash2, 0); 69 bool flag = false; 70 for(int i = 1; i <= n; i++) { 71 int len = min(a[i] - 1, n - a[i]); 72 ll ans1 = query1(1,1,n,a[i] - len,a[i] - 1); 73 ll ans2 = query2(1,1,n,a[i] + 1,a[i] + len); 74 if(ans1 != ans2) { 75 flag = true; 76 break; 77 } 78 update(1,1,n,a[i]); 79 } 80 if(flag) puts("Y"); 81 else puts("N"); 82 } 83 return 0; 84 }