CodeForces 213 E

 1 /*
 2     线段树 + hash:
 3     首先我们可以知道A序列是1~n的排列,那么我们可以先在B序列中把1~n的排列找出来,看其相对位置是否与A相同(hash可做),相同即表明存在一个d满足条件。
 4     以此类推,我们接下来可以把B中 2~ n + 1的排列找出来,如果其每位-1后相对顺序还是与A序列一致,即存在d-1也满足。。。
 5     线段树中保存一个长度为n的序列的hash。具体看代码
 6 */
 7 #include <bits/stdc++.h>
 8 
 9 using namespace std;
10 
11 #define lson l, m ,rt<<1
12 #define rson m + 1, r, rt <<1|1
13 const int maxn = 2e5 + 5;
14 const int M = 10007;//hash底数
15 typedef long long ll;
16 int pw[maxn], s, h;
17 int n, m;
18 
19 int hash[maxn << 2],sz[maxn << 2];
20 void pushUp(int rt){
21     hash[rt] = hash[rt<<1] * pw[sz[rt<<1|1]] + hash[rt<<1|1];
22     sz[rt] = sz[rt<<1] + sz[rt<<1|1];
23 }
24 void update(int p, int val, int tag, int l, int r, int rt){
25     if (l == r){
26         hash[rt] += tag * val;
27         sz[rt] += tag;
28         return ;
29     }
30     int m = (l + r) >> 1;
31     if (p <= m) update(p, val, tag, lson);
32     else update(p, val, tag, rson);
33     pushUp(rt);
34 }
35 int pos[maxn];
36 int main(){
37     int x;
38     while (~scanf("%d%d", &n, &m)){
39         pw[0] = 1;
40         h = s = 0;
41         for (int i = 1; i <= n; ++i){
42             scanf("%d", &x);
43             h = h * M + x;
44             pw[i] = pw[i - 1] * M;//M的i次方
45             s += pw[i - 1];//1 ~n的排列的hash转化成 2 ~ n + 1的hash需要+s.......自己算算
46         }
47         for (int i = 1; i <= m; ++i){
48             scanf("%d", &x);
49             pos[x] = i;
50         }
51         memset(hash, 0, sizeof(hash));
52         memset(sz, 0, sizeof(sz));
53         int ans = 0;
54         for (int i = 1; i <= m; ++i){
55             update(pos[i], i, 1, 1, m, 1);
56             if (i >= n){
57                 if ((hash[1] - (s * (i - n)) == h))
58                     ans++;
59                 update(pos[i - n + 1], i - n + 1, -1, 1, m, 1);
60             }
61         }
62         printf("%d\n", ans);
63     }
64     return 0;
65 }

 

posted @ 2013-11-28 14:52  Missa  阅读(666)  评论(0编辑  收藏  举报