• [SDOI2019]快速查询


    题目

    就是一个签到题啊,然而没有判乘0于是签到失败成功退役

    模数只有(1e7+19)于是我们可以线性求所有逆元了

    我们只需要考虑如何解决操作1和操作5即可,其余的操作就是简单的模拟一下即可

    发现操作1和操作5还是本质上就是询问一个单点的值

    注意到实际上有用的位置只有(1e5)个,于是我们可以离散化一下

    对于每一个位置存好这个位置上一次的赋值操作在哪一次

    我们处理一个所有乘法操作的后缀积,和加法操作乘对应位置的后缀积的和就能(O(1))回答了

    但是这样不能处理乘0的情况

    其实非常简单,我们只需要把乘0看成整体赋值成0即可

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read() {
    	char c=getchar();int x=0,r=1;
    	while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return r*x;
    }
    const int mod=1e7+19;
    const int maxn=1e5+5;
    int n,T,Q,v,sz,tot;
    int inv[mod],s[mod],p[mod];
    int c[maxn],a[105],b[105];
    int op[maxn],val[maxn],pos[maxn],g[maxn],h[maxn];
    inline int find(int x) {
    	int l=1,r=sz;
    	while(l<=r) {
    		int mid=l+r>>1;
    		if(c[mid]==x) return mid;
    		if(c[mid]<x) l=mid+1;else r=mid-1;
    	}
    	return 0;
    }
    inline int ask(int x,int y,int now) {
    	int k;
    	if(g[x]<y) k=(1ll*v*s[y]%mod+p[y]-p[now+1]+mod)%mod;
    		else k=(1ll*h[x]*s[g[x]]%mod+p[g[x]]-p[now+1]+mod)%mod;
    	return 1ll*k*inv[s[now+1]]%mod;
    }
    int main() {
    	n=read();Q=read();inv[1]=1;
    	for(re int i=2;i<mod;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    	for(re int i=1;i<=Q;i++) {
    		op[i]=read();
    		if(op[i]==6) continue;
    		val[i]=read();
    		if(op[i]>=2&&op[i]<=4) continue;
    		if(op[i]==5) {pos[i]=val[i];val[i]=0;continue;}
    		pos[i]=read();std::swap(val[i],pos[i]);
    	}
    	for(re int i=1;i<=Q;i++) 
    		val[i]%=mod,val[i]=(val[i]+mod)%mod;
    	for(re int i=1;i<=Q;i++) if(op[i]==3&&!val[i]) op[i]=4;
    	for(re int i=1;i<=Q;i++) if(op[i]==5||op[i]==1) c[++tot]=pos[i];
    	std::sort(c+1,c+tot+1);sz=std::unique(c+1,c+tot+1)-c-1;
    	for(re int i=1;i<=Q;i++) if(op[i]==5||op[i]==1) pos[i]=find(pos[i]);
    	T=read();
    	for(re int i=1;i<=T;i++) a[i]=read(),b[i]=read();
    	s[T*Q+1]=1;
    	for(re int i=T;i;--i)
    		for(re int j=Q;j;--j) {
    			int x=(i-1)*Q+j;
    			int y=(a[i]+1ll*j*b[i]%Q)%Q+1;
    			if(op[y]==2) p[x]=val[y];else p[x]=0;
    			if(op[y]==3) s[x]=val[y];else s[x]=1;
    			s[x]=1ll*s[x+1]*s[x]%mod;
    			p[x]=(p[x+1]+1ll*p[x]*s[x]%mod)%mod;
    		}
    	s[0]=s[1],p[0]=p[1];n%=mod;
    	int ans=0,sum=0,lst=0;
    	for(re int i=1;i<=T;i++)
    		for(re int j=1;j<=Q;j++) {
    			int x=(i-1)*Q+j;
    			int y=(a[i]+1ll*j*b[i]%Q)%Q+1;
    			if(op[y]==6) {ans=(ans+sum)%mod;continue;}
    			if(op[y]==2) {sum=(sum+1ll*n*val[y]%mod)%mod;continue;}
    			if(op[y]==3) {sum=1ll*sum*val[y]%mod;continue;}
    			if(op[y]==4) {v=val[y];lst=x;sum=1ll*n*val[y]%mod;continue;}
    			if(op[y]==5) {ans=(ans+ask(pos[y],lst,x))%mod;continue;}
    			if(op[y]==1) {
    				int t=pos[y];
    				sum=(sum-ask(t,lst,x)+mod)%mod;
    				sum=(sum+val[y])%mod;
    				g[t]=x;h[t]=val[y];
    			}
    		}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    NSIS 资料
    git 强制刷新,放弃更改
    Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 8
    …gen already exists but is not a source folder. Convert to a source folder or rename it [closed]
    eclipse
    Timeout in android httpclient
    git command
    L1-032. Left-pad
    L1-030. 一帮一
    L1-028. 判断素数
  • 原文地址:https://www.cnblogs.com/asuldb/p/10846898.html
Copyright © 2020-2023  润新知