• 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 }
  • 相关阅读:
    codeforces 368(div 2)前三题
    codeforces 368(div 2)前三题
    hihocoder编程练习赛6+多重背包的各种姿势
    hihocoder编程练习赛6+多重背包的各种姿势
    hihocoder1077,线段树单点修改的一点小技巧
    hihocoder1077,线段树单点修改的一点小技巧
    [NOIP2013]货车运输,最大生成树+LCA
    [NOIP2013]货车运输,最大生成树+LCA
    hihocoder 1080 线段树:区间加法&赋值
    hihocoder 1080 线段树:区间加法&赋值
  • 原文地址:https://www.cnblogs.com/scaulok/p/9871691.html
Copyright © 2020-2023  润新知