Luogu6080 [USACO05DEC]Cow Patterns G

Posted yspm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
",cnt); for(int i=1;i<=cnt;++i) printf("%lld
",ans[i]); 
		return 0;
	}
}
signed main(){return yspm::main();}

以上是关于Luogu6080 [USACO05DEC]Cow Patterns G的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3000 [USACO10DEC]牛的健美操Cow Calisthenics

[Luogu2870] [USACO07DEC]最佳牛线Best Cow Line(贪心+后缀数组)

洛谷 2966 [USACO09DEC]牛收费路径Cow Toll Paths

P7990-[USACO21DEC]Closest Cow Wins S堆,贪心

P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold

洛谷P2853 [USACO06DEC]Cow Picnic S 题解