联考20200612 T2 「雅礼集训 2018 Day11」字符串

题目传送门

分析:
集合G的成功的答案不好算,我们可以用1减去失败的概率,失败的的情况只可能是随机区间在G相邻两个元素之间
我们考虑集合删除,最暴力的就是使用Set直接删除
单次删除\(O(logn)\)不优,这道题维护信息只考虑删除的话可以使用双向链表
但是插入就麻烦了,我们不知道当前插入的关键点在哪里,需要二分,怎么做到\(O(1)\)
我们先把所有的字符串放进去检验,可以把Trie上的所有点的\(f\)求出来,并求出集合\(G\)
这样所有的关键点都求了出来,我们就可以保存好关键点\(O(1)\)插入了
可以使用莫队,但是链表插入时,插入的顺序必须严格对应之前删除的顺序,否则双向链表就会出现错误
于是使用黑科技:回滚莫队,不会的童鞋可以看看这篇博客
然后直接维护就好了

#include
#include
#include
#include
#include
#include
#include

#define maxn 300005
#define INF 0x3f3f3f3f

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,A,B,C,L,S,Q;
struct node{
	int l,r,id;
}q[maxn];
char s[maxn];
int val[maxn],len[maxn],bl[maxn],g[maxn];
int ch[maxn][26],dpt[maxn],cur;
int p[maxn],tot,pos[maxn],v[maxn],b[maxn];
int stk[maxn],tp;
int l[maxn],r[maxn];
long long F[maxn],ans[maxn];
long long Sum,Now;
inline bool cmp(node x,node y){return bl[x.l]==bl[y.l]?x.r>y.r:x.l=C:0;}
inline void add(int i)
{
	int x=pos[i];
	if(!check(F[x],dpt[x])&&check(F[x]+v[i],dpt[x])&&!(b[g[dpt[x]]]++))
	{
		int k=g[dpt[x]],ll=l[k],rr=r[k];
		r[ll]=k,l[rr]=k,Now+=cal(rr-ll-1),Now-=cal(k-ll-1),Now-=cal(rr-k-1);
	}
	F[x]+=v[i];
}
inline void del(int i)
{
	int x=pos[i];
	if(check(F[x],dpt[x])&&!check(F[x]-v[i],dpt[x])&&!(--b[g[dpt[x]]]))
	{
		int k=g[dpt[x]],ll=l[k],rr=r[k];
		r[ll]=rr,l[rr]=ll,Now-=cal(rr-ll-1),Now+=cal(k-ll-1),Now+=cal(rr-k-1);
	}
	F[x]-=v[i];
}

int main()
{
	n=getint(),A=getint(),B=getint(),C=getint();
	for(int i=1;i<=n;i++)val[i]=getint();
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1),L=max(L,len[i]=strlen(s+1));
		insert(i),len[i]+=len[i-1];
	}
	S=sqrt(tot);
	for(int i=1;i<=tot;i++)bl[i]=(i-1)/S+1;
	for(int i=1;i<=L;i++)g[i]=getint();
	Q=getint();
	Now=Sum=cal(L);
	for(int i=1;i<=Q;i++)
		q[i].l=len[getint()-1]+1,q[i].r=len[getint()],q[i].id=i;
	sort(q+1,q+Q+1,cmp);
	for(int i=1,x=pos[i];i<=tot;i++,x=pos[i])
	{
		if(!check(F[x],dpt[x])&&check(F[x]+v[i],dpt[x])&&!(b[g[dpt[x]]]++))
			stk[++tp]=g[dpt[x]];
		F[x]+=v[i];
	}
	stk[++tp]=0,stk[++tp]=L+1;sort(stk+1,stk+tp+1);
	for(int i=1;i<=tp;i++)l[stk[i]]=stk[i-1],r[stk[i]]=stk[i+1];
	for(int i=2;i<=tp;i++)Now-=cal(stk[i]-stk[i-1]-1);
	for(int i=1,j=S,now=1,l=i,r=tot;i<=tot&&now<=Q;i+=S,j+=S)
	{
		while(now<=Q&&q[now].l>=i&&q[now].l<=j)
		{
			while(r>q[now].r)del(r--);while(li)add(--l);now++;
		}
		while(r

你可能感兴趣的:(联考20200612 T2 「雅礼集训 2018 Day11」字符串)