【题解】Luogu P5358 [SDOI2019]快速查询

原题传送门

神鱼说这道题是强制离线(smog

我们珂以把被单点修改,单点查询的点单独拿出来处理,把每个数表示成\(mul*x+plus\)

初始状态下\(mul=1,plus=0\)

操作1:在总和中减去\(val[pos[x]]\)\(pos\)表示离散化后的位置,\(val\)表示特殊点的数值);将\(val[pos[x]]\)变成\(\frac{val_{new}-plus}{mul}\);如果\(pos[x]\)不在非零位置的栈中,将\(pos[x]\)压入栈中;在总和中加上\(val_{new}\)

操作2:将\(plus\)加上\(val\),将总和更新

操作3:当乘的值不为\(0\)时,将\(mul\)\(plus\)和总和都乘上这个值;当乘的值为\(0\)时,将所有数赋值为\(0\),见操作4

操作4:把值不为\(0\)的栈弹空,并将\(val[sta[top]]\)变成\(0\),并且将\(mul\)变成\(1\),将\(plus\)变成\(val\),将总和更新

操作5/6:val[pos[x]]或总和

有除法,要处理逆元

#include <bits/stdc++.h>
#define N 100005
#define mod 10000019
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int fastpow(register int a,register int b)
{
	int res=1;
	while(b)
	{
		if(b&1)
			res=1ll*res*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return res;
}
int n,m,t,ans,b[N*100],tot,sum,mul=1,pls,inv=1,f[N],in[N];
inline void modify(register int x,register int y)
{
	sum=(sum+1ll*(mod-f[x])*mul+mod-pls)%mod;
	f[x]=1ll*(y-pls+mod)*inv%mod;
	if(!in[x])
		b[++tot]=x,in[x]=1;
	sum=(sum+y)%mod;
}
inline void plu(register int y)
{
	sum=(sum+1ll*n*y)%mod;
	pls=(pls+y)%mod;
}
inline void cover(register int y)
{
	while(tot)
		f[b[tot]]=0,in[b[tot--]]=0;
	mul=inv=1,pls=y;
	sum=1ll*n*y%mod;
}
inline void mult(register int y,register int z)
{
	if(y)
	{
		sum=1ll*sum*y%mod;
		mul=1ll*mul*y%mod;
		pls=1ll*pls*y%mod;
		inv=1ll*inv*z%mod;
	}
	else
		cover(0);
}
inline int query(register int x)
{
	return (1ll*f[x]*mul+pls)%mod;
}
int opt[N],x[N],y[N],z[N];
int main()
{
	n=read()%mod,m=read();
	for(register int i=0;i<m;++i)
	{
		opt[i]=read();
		if(opt[i]==1||opt[i]==5)
			x[i]=b[++tot]=read();
		if(opt[i]<=4)
			y[i]=(read()%mod+mod)%mod,z[i]=fastpow(y[i],mod-2);
	}
	sort(b+1,b+1+tot);
	tot=unique(b+1,b+1+tot)-b-1;
	for(register int i=0;i<m;++i)
		if(opt[i]==1||opt[i]==5)
			x[i]=lower_bound(b+1,b+1+tot,x[i])-b;
	t=read();
	for(register int i=tot=0;i<t;++i)
	{
		int a=read()%m,b=read()%m;
		for(register int j=0,k=(a+b)%m;j<m;++j,k=(k+b)%m)
		{
			int o=opt[k];
			if(o==1)
				modify(x[k],y[k]);
			else if(o==2)
				plu(y[k]);
			else if(o==3)
				mult(y[k],z[k]);
			else if(o==4)
				cover(y[k]);
			else if(o==5)
				ans=(ans+query(x[k]))%mod;
			else 
				ans=(ans+sum)%mod;
		}
	}
	write(ans);
	return 0;
}

posted @ 2019-06-01 21:25  JSOI爆零珂学家yzhang  阅读(846)  评论(0编辑  收藏  举报