Luogu6080 [USACO05DEC]Cow Patterns G

Description

link 其实就是 \(bzoj1461\)

一般的 \(kmp\) 我们求的是相等的部分

现在给定数字串,求大小关系相等的个数

Solution

其实还是 \(kmp\)

改变的地方我们把那个判断相等改成用树状数组

具体就是看值域前面的数的个数

\(nxt\) 比较简单,根据 \(kmp\) 的原理来的

每次跳的时候把原来的值都得清空掉

(不太好写,细节有点点多)

然后查询也是板子套树状数组

这里我发现网上使用一棵 \(BIT\) 的做法无法通过洛谷的数据

然后去找到了一份用两个的

(一个 \(BIT\) 的正确性确实……其实是他们没有清空完……)

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mp make_pair
#define pii pair<int,int>
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar(); 
		return res*f;
	}
	const int N=5e5+10;
	int n,m,s,a[N],b[N],nxt[N],l[N],e[N],ans[N],cnt;
	struct BIT{
		int c[N];
		inline int lowbit(int x){return x&(-x);}
		inline void add(int x,int y){for(;x<=s;x+=lowbit(x)) c[x]+=y; return ; }
		inline int ask(int x){int res=0; for(;x;x-=lowbit(x)) res+=c[x]; return res;}
		inline void clear(){return memset(c,0,sizeof(c)),void();}
	}t1,t2;
	inline pii get1(int p){return mp(t1.ask(p),t1.ask(p-1));}
	inline pii get2(int p){return mp(t2.ask(p),t2.ask(p-1));}
	signed main()
	{
//		freopen("1.in","r",stdin);
		n=read(); m=read(); s=read();
		for(int i=1;i<=n;++i) a[i]=read();
		for(int i=1;i<=m;++i) b[i]=read();
		t1.clear(); t2.clear();
		for(int i=2,j=0;i<=m;++i)
		{
			while(j) 
			{
				pii x=get1(b[j+1]),y=get2(b[i]);
				if(x==y) break;
				for(int k=nxt[j]+1;k<=j;++k) t1.add(b[k],-1);
				for(int k=i-j;k<i-nxt[j];++k) t2.add(b[k],-1);
				j=nxt[j];
			}
			pii x=get1(b[j+1]),y=get2(b[i]);
			if(x==y) t1.add(b[j+1],1),t2.add(b[i],1),++j;
			nxt[i]=j;
		}
		t1.clear(); t2.clear();
		for(int i=1,j=0;i<=n;++i)
		{
			while(j)
			{
				pii x=get1(b[j+1]),y=get2(a[i]);
				if(x==y) break;
				for(int k=nxt[j]+1;k<=j;++k) t1.add(b[k],-1);
				for(int k=i-j;k<i-nxt[j];++k) t2.add(a[k],-1);
				j=nxt[j]; 
			}
			pii x=get1(b[j+1]),y=get2(a[i]);
			if(x==y) t1.add(b[j+1],1),t2.add(a[i],1),++j;
			if(j==m)
			{
				ans[++cnt]=i-m+1;
				for(int k=nxt[j]+1;k<=j;++k) t1.add(b[k],-1);
				for(int k=i-j+1;k<=i-nxt[j];++k) t2.add(a[k],-1);
				j=nxt[j];
			}
		}  
		printf("%lld\n",cnt); for(int i=1;i<=cnt;++i) printf("%lld\n",ans[i]); 
		return 0;
	}
}
signed main(){return yspm::main();}

猜你喜欢

转载自www.cnblogs.com/yspm/p/12945663.html