• 【题解】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;
    }
    
    
  • 相关阅读:
    云计算
    uc/xi
    互联网 2.0概念
    java连接数据库
    记录一下安装 mysql 的踩坑之路
    1
    Linux介绍与基本必知命令
    Web课程Linux命令统计
    7——条件判断、三目运算、条件循环、迭代循环
    6——散列类型、运算符优先级、逻辑运算
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10961064.html
Copyright © 2020-2023  润新知