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 }

 

posted on 2018-10-29 17:05  scau_lok  阅读(218)  评论(0编辑  收藏  举报

导航