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

CF587F. Duff is Mad

时间:2020-09-21 11:52:07      阅读:32      评论:0      收藏:0      [点我收藏+]

标签:mem   loading   bool   png   end   递归   print   turn   n+1   

题目描述

技术图片

题解

知道是分块之后就不难了

把n分块,对于整块建AC自动机暴力跑,散块把全部串建AC自动机之后可以线段树查子树(因为往上查要考虑那些能查那些不能所以不好搞),也可以递归子树时用 出-入 计算

空间卡一卡可以\(n\sqrt n\),如果再把询问[L,R]前缀和一下之后也许可以做到线性

时间O(n√n)

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

int bg[100001],ed[100001],A[100011],Tm[100001],n,Q,i,j,k,l,len,S,x,y;
bool bz[100001];
ll ans[100001],Ans[100001];
char st[100001],St[100001];
struct type{int x,y,z;} q[100001];

namespace tree{
	int a[100011][2],b[50000001],ls[100011],tr[100011][26],fa[100011],d[100011],Ed[100011],i,j,k,l,len=0,h,t,Len;
	vector<int> c[100011];
	ll f[100011];
	
	void clear() {memset(tr,0,sizeof(tr[0])*(len+1));memset(fa,0,4*(len+1));memset(f,0,8*(len+1));len=0;}
	void New(int t,int x) {if (!tr[t][x]) tr[t][x]=++len;}
	void NEW(int x,int y) {++Len;a[Len][0]=y;a[Len][1]=ls[x];ls[x]=Len;}
	void dfs(int t)
	{
		int i,j,k,l,tot2=c[t].size(),s;
		
		fo(i,Ed[t-1]+1,Ed[t]) s=b[i],ans[s]-=f[q[s].z];
		fo(i,0,tot2-1) ++f[c[t][i]];
		
		for (i=ls[t]; i; i=a[i][1]) dfs(a[i][0]);
		
		fo(i,Ed[t-1]+1,Ed[t]) s=b[i],ans[s]+=f[q[s].z];
	}
	void build(int x,int y,int tp)
	{
		clear(),len=1;
		fo(i,x,y)
		{
			l=1;
			fo(j,bg[i],ed[i])
			{
				New(l,st[j]-‘a‘),l=tr[l][st[j]-‘a‘];
				if (tp) c[l].push_back(i);
			}
			
			if (!tp) ++f[l];
			A[i]=l;
		}
		
		if (tp)
		{
			fo(i,1,Q)
			{
				for (j=1; j<=n; j+=S)
				{
					k=min(j+S-1,n);
					if (!(q[i].x<=j && k<=q[i].y) || !bz[i])
					fo(l,max(q[i].x,j),min(q[i].y,k)) ++Ed[A[l]];
				}
			}
			fo(i,1,len) Ed[i]+=Ed[i-1];
			fd(i,len+1,1) Ed[i]=Ed[i-1];
			fo(i,1,Q)
			{
				for (j=1; j<=n; j+=S)
				{
					k=min(j+S-1,n);
					if (!(q[i].x<=j && k<=q[i].y) || !bz[i])
					{
						fo(l,max(q[i].x,j),min(q[i].y,k))
						b[++Ed[A[l]]]=i;
					}
				}
			}
		}
		
		h=0,t=1;
		d[1]=1;
		while (h<t)
		{
			++h;
			fo(i,0,25)
			if (tr[d[h]][i])
			{
				l=tr[d[h]][i];
				d[++t]=l;
				
				j=fa[d[h]];
				while (j && !tr[j][i]) j=fa[j];
				fa[l]=(!j)?1:tr[j][i];
			}
		}
		
		if (!tp)
		{
			fo(i,1,t)
			f[d[i]]+=f[fa[d[i]]];
		}
		else
		{
			fo(i,2,len) NEW(fa[i],i);
			dfs(1);
		}
	}
	
	void js(int t,int id)
	{
		ll s=0;
		if (Tm[t]==x) {ans[id]+=Ans[t];return;}
		l=1;
		fo(i,bg[t],ed[t])
		{
			while (l && !tr[l][st[i]-‘a‘]) l=fa[l];
			if (!l) l=1; else l=tr[l][st[i]-‘a‘];
			s+=f[l];
		}
		Tm[t]=x,Ans[t]=s,ans[id]+=s;
	}
};

int main()
{
	#ifdef file
	freopen("CF587F.in","r",stdin);
	#endif
	
	scanf("%d%d",&n,&Q),S=floor(sqrt(n));
	fo(i,1,n)
	{
		scanf("%s",St+1),l=strlen(St+1);
		bg[i]=len+1;
		fo(j,1,l) st[++len]=St[j];
		ed[i]=len;
	}
	fo(i,1,Q) scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
	
	for (x=1; x<=n; x+=S)
	{
		y=min(x+S-1,n);
		tree::build(x,y,0);
		
		fo(i,1,Q)
		if (q[i].x<=x && y<=q[i].y)
		tree::js(q[i].z,i),bz[i]=1;
	}
	tree::build(1,n,1);
	
	fo(i,1,Q) printf("%lld\n",ans[i]);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

CF587F. Duff is Mad

标签:mem   loading   bool   png   end   递归   print   turn   n+1   

原文地址:https://www.cnblogs.com/gmh77/p/13693727.html

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