码迷,mamicode.com
首页 > 其他好文 > 详细

CF213E Two Permutations 线段树维护哈希值

时间:2019-06-16 00:37:41      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:const   线段   div   main   vector   reg   gis   code   out   

当初竟然看成子串了$qwq$,不过老师的$ppt$也错了$qwq$


 

由于子序列一定是的排列,所以考虑插入$1$到$m$到$n-m+1$到$n$;

如何判断呢?可以用哈希$qwq$;

我们用线段树维护哈希值,合并时用就把左子树的哈希值$x[ls]$在$B$进制下左移$sum[rs]$位,即$x[tr]=x[ls]*p[sum[rs]]+x[rs]$;

此时就可以向上更新哈希值。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ull unsigned long long
#define ll long long
#define R register int
#define md ((l+r)>>1)
#define ls (tr<<1)
#define rs (tr<<1|1)
#define pause (for(R i=1;i<=10000000000;++i))
#define OUT freopen("out.out","w",stdout)
using namespace std;
namespace Fread {
    static char B[1<<15],*S=B,*D=B;
    #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==-?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    } inline bool isempty(const char& ch) {return ch<=36||ch>=127;}
    inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));}
}using Fread::g; using Fread::gs;
const int B=23,N=200010;
int n,m,s[N],a[N],pos[N],ans;
ull x[N<<2],sum[N<<2],p[N],cnt,hsh;
inline void upd(int tr,int l,int r) {
    sum[tr]=sum[ls]+sum[rs];
    x[tr]=x[ls]*p[sum[rs]]+x[rs];
}
inline void change(int tr,int l,int r,int pos,int d) {
    if(l==r) {sum[tr]+=(d?1:-1); x[tr]=d; return ;} 
    if(pos<=md) change(ls,l,md,pos,d);
    else change(rs,md+1,r,pos,d); upd(tr,l,r);
}
signed main() {
#ifdef JACK
    freopen("NOIPAK++.in","r",stdin);
#endif 
    m=g(),n=g(); p[0]=1; for(R i=1;i<=m;++i) p[i]=p[i-1]*B;
    for(R i=1;i<=m;++i) s[i]=g(),hsh=hsh*B+s[i],cnt+=p[i-1];
    for(R i=1;i<=n;++i) a[i]=g(),pos[a[i]]=i;
    for(R i=1;i<=n;++i) {
        if(i>m) change(1,1,n,pos[i-m],0);
        change(1,1,n,pos[i],i);
        R d=i-m; if(d>=0&&x[1]==d*cnt+hsh) ++ans;
    } printf("%d\n",ans);
} 

2019.06.15

 

CF213E Two Permutations 线段树维护哈希值

标签:const   线段   div   main   vector   reg   gis   code   out   

原文地址:https://www.cnblogs.com/Jackpei/p/11029377.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!