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

Luogu6080 [USACO05DEC]Cow Patterns G

时间:2020-05-24 09:43:53      阅读:52      评论:0      收藏:0      [点我收藏+]

标签:com   +=   printf   部分   git   lang   clu   数字   math   

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();}

Luogu6080 [USACO05DEC]Cow Patterns G

标签:com   +=   printf   部分   git   lang   clu   数字   math   

原文地址:https://www.cnblogs.com/yspm/p/12945663.html

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