您的位置:首页 > 其它

BZOJ 3207: 花神的嘲讽计划Ⅰ|莫队|主席树|hash

2016-02-20 09:31 435 查看
本来以为会卡主席树内存,然后写了莫队T到死,发现想多了……

然而这题并不卡内存,直接主席树做就好了。

先给长度为K的序列hash一下然后就变成了询问一个区间内有没有某一个数,我离散化了一下,然后改成主席树发现又T到死……woc…终于发现二分查找有鬼..

然后就发现似乎莫队和主席树的二分都是一样的都有鬼..改了一下发现都能过,而且,而且莫队比主席树要快!!!!!!!!!!

发现主席树似乎并不需要离线离散化,只要强行扩大保存的区间的范围就好,因为复杂度是log的所以强行扩大范围的话复杂度多不了多少

code,主席树

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define ll unsigned long long
#define N 500022
using namespace std;
int sc()
{
int i=0,f=1; char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i*f;
}
struct W{int l,r,pos;ll v;}A
;
struct U{int pos;ll v;}h
;
ll hash
,a
,bin
;
int sum
,v
,ans
,root
;
int n,m,k,tot,cnt;
int ch[5001000][2],sm[5001000];
bool cmp(U a,U b)
{
return a.v<b.v;
}
void add(int pre,int &x,int l,int r,int v)
{
if(!x)x=++cnt;
sm[x]=sm[pre]+1;
if(l==r)return;
int mid=l+r>>1;
if(v>mid)
ch[x][0]=ch[pre][0],
add(ch[pre][1],ch[x][1],mid+1,r,v);
else
ch[x][1]=ch[pre][1],
add(ch[pre][0],ch[x][0],l,mid,v);
}
int ask(int L,int R,int v)
{
int l=1,r=tot;
while(l!=r)
{
int mid=l+r>>1,e=(v>mid);
e?l=mid+1:r=mid;
L=ch[L][e],R=ch[R][e];
if(sm[R]-sm[L]==0)return 0;
}
return sm[R]-sm[L];
}
int main()
{
n=sc(),m=sc(),k=sc();bin[0]=1;
for(int i=1;i<=n;i++)
{
a[i]=a[i-1]*233+sc();
bin[i]=bin[i-1]*233;
}
for(int i=k;i<=n;i++)
h[i-k+1].v=a[i]-a[i-k]*bin[k],
h[i-k+1].pos=i-k+1;
n=n-k+1;
sort(h+1,h+n+1,cmp);
for(int i=1;i<=n;i++)
v[h[i].pos]=(h[i].v==h[i-1].v?tot:++tot),
hash[tot]=h[i].v;
for(int i=1;i<=n;i++)
add(root[i-1],root[i],1,tot,v[i]);
for(int i=1;i<=m;i++)
{
A[i].l=sc();
A[i].r=sc()-k+1;
for(int j=1;j<=k;j++)A[i].v=A[i].v*233+sc();
int x=lower_bound(hash+1,hash+tot+1,A[i].v)-hash;
if(hash[x]!=A[i].v||A[i].r<A[i].l)puts("Yes");
else
{
if(ask(root[A[i].l-1],root[A[i].r],x)) puts("No");
else puts("Yes");
}
}
return 0;
}


code,莫队

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define ll unsigned long long
#define N 500022
using namespace std;
int sc()
{
int i=0,f=1; char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i*f;
}
struct W{int l,r,pos;ll v;}A
;
struct U{int pos;ll v;}h
;
ll hash
,a
,bin
;
int sum
,bl
,v
,ans
;
int n,m,k,block,tot;
bool cmp(U a,U b)
{
return a.v<b.v;
}
bool cmp1(W a,W b)
{
return bl[a.l]==bl[b.l]?a.r<b.r:bl[a.l]<bl[b.l];
}
int find(ll x)
{
int l=1,r=tot;
while(l<r)
{
int mid=l+r>>1;
if(hash[mid]==x)return mid;
else if(hash[mid]<x) l=mid+1;
else r=mid-1;
}
return hash[l]==x?l:0;
}
int main()
{
n=sc(),m=sc(),k=sc();block=sqrt(n);bin[0]=1;
for(int i=1;i<=n;i++)
{
bl[i]=(i-1)/block+1;
a[i]=a[i-1]*233+sc();
bin[i]=bin[i-1]*233;
}
for(int i=k;i<=n;i++)
h[i-k+1].v=a[i]-a[i-k]*bin[k],
h[i-k+1].pos=i-k+1;
n=n-k+1;
sort(h+1,h+n+1,cmp);
for(int i=1;i<=n;i++)
v[h[i].pos]=(h[i].v==h[i-1].v?tot:++tot),
hash[tot]=h[i].v;
for(int i=1;i<=m;i++)
{
A[i].l=sc();
A[i].r=sc()-k+1;
A[i].pos=i;
for(int j=1;j<=k;j++)A[i].v=A[i].v*233+sc();
}
sort(A+1,A+m+1,cmp1);
int l=1,r=0;
for(int i=1;i<=m;i++)
{
int x=find(A[i].v);
if(!x||A[i].r<A[i].l)continue;
while(l<A[i].l)sum[v[l++]]--;
while(l>A[i].l)sum[v[--l]]++;
while(r>A[i].r)sum[v[r--]]--;
while(r<A[i].r)sum[v[++r]]++;
if(sum[x])ans[A[i].pos]=1;
}
for(int i=1;i<=m;i++)ans[i]?puts("No"):puts("Yes");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  莫队 主席树 hash