并不对劲的loj3110:p5358:[SDOI2019]快速查询

题目大意

\(n\)个数,对这些数进行\(t\times q\)次操作,操作有单点修改、全局加、全局乘、全局修改、单点询问、全局求和这几种。
\(t\times q\)次操作中,每次操作都是来自于给出的\(q\)次基本操作之一。输出所有询问操作的和模\(10^7+19\)
\(n\leq 10^9;q\leq 10^5;t\leq 100;-10^9\leq 操作中涉及的值 \leq 10^9\)

题解

只用存\(\leq 10^5\)个单点修改操作涉及的点。
正常的做法:维护全局加标记、乘标记、修改标记,单点修改时将这个点的值改为\((值+加法逆元)\times 乘法逆元\)
并不对劲的做法:维护每个时刻的加标记、乘标记、修改标记、每个点上次修改的时刻,单点查询时,如果该点上次的修改操作是单点修改,值=\((修改的数\times 当前乘标记\times修改时乘标记的逆元)+(当前加标记+修改时加标记的逆元\times(当前乘标记\times修改时乘标记的逆元))\)
预处理逆元。

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 100007
#define maxx 10000027
#define maxm 10000007
#define LL long long
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
void write(int x)
{
	if(x==0){putchar('0'),putchar('\n');return;}
	int f=0;char ch[20];
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10+'0',x/=10;
	while(f)putchar(ch[f--]);
	putchar('\n');
	return;
}
int t,a[maxn],b[maxn],n,q,pw[maxx],ny[maxx],mulmk[maxm],admk[maxm],lst[maxn],mkx[maxn],num[maxn],cntn,lstmk;
int qf[maxn],qx[maxn],qy[maxn],ans,nowsum;
const int mod=1e7+19;
int mul(int x,int y){int res=1;while(y){if(y&1)res=(LL)res*x%mod;x=(LL)x*x%mod,y>>=1;}return res;}
int getrk(int k)
{
	int L=1,R=cntn,res=cntn+1;
	while(L<=R)
	{
		int mid=(L+R)>>1;
		if(num[mid]>=k)res=min(res,mid),R=mid-1;
		else L=mid+1;
	}
	return res;
}
int mo(int x){if(x<0)return x+mod;return x>=mod?x-mod:x;}
int main()
{
	pw[0]=1;rep(i,1,mod-1)pw[i]=(LL)pw[i-1]*i%mod;
	ny[mod-1]=mul(pw[mod-1],mod-2);dwn(i,mod-2,0)ny[i]=(LL)ny[i+1]*(i+1)%mod;
	rep(i,1,mod-1)ny[i]=(LL)ny[i]*pw[i-1]%mod;
	n=read(),q=read();
	rep(i,1,q)
	{
		qf[i]=read();
		if(qf[i]==6)continue;
		else if(qf[i]==1)qx[i]=read(),qy[i]=mo(read()%mod);
		else qx[i]=read(); 
		if(qf[i]==1)num[++cntn]=qx[i];
		if(qf[i]==2||qf[i]==3||qf[i]==4)qx[i]=mo(qx[i]%mod);
	}
	t=read();
	sort(num+1,num+cntn+1);
	rep(i,1,t)a[i]=read(),b[i]=read();
	rep(i,1,q)
	{
		if(qf[i]==1){qx[i]=getrk(qx[i]);}
		else if(qf[i]==5){int qq=getrk(qx[i]);if(num[qq]==qx[i])qx[i]=qq;else qx[i]=-1;}
		if(qf[i]==3&&qx[i]==0)qf[i]=4;
	}
	admk[0]=0,mulmk[0]=1;n%=mod;
	rep(i,1,t)rep(j,1,q)
	{
		int p=((LL)a[i]+(LL)j*b[i])%q+1,pp=(i-1)*q+j;
		if(qf[p]==1)
		{
			int val=0;admk[pp]=admk[pp-1],mulmk[pp]=mulmk[pp-1];
			if(lstmk>=lst[qx[p]])val=admk[pp];
			else val=mo((LL)mkx[qx[p]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod+mo(admk[pp]-(LL)admk[lst[qx[p]]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod));
			nowsum=mo(nowsum+mo(qy[p]-val)),lst[qx[p]]=pp,mkx[qx[p]]=qy[p]; 
		}
		else if(qf[p]==2)
		{
			admk[pp]=mo(admk[pp-1]+qx[p]),mulmk[pp]=mulmk[pp-1];
			nowsum=mo(nowsum+(LL)n*qx[p]%mod);
		}
		else if(qf[p]==3)
		{
			admk[pp]=(LL)admk[pp-1]*qx[p]%mod,mulmk[pp]=(LL)mulmk[pp-1]*qx[p]%mod;
			nowsum=(LL)nowsum*qx[p]%mod;
		}
		else if(qf[p]==4)
		{
			lstmk=pp,admk[pp]=qx[p],mulmk[pp]=1;
			nowsum=(LL)n*qx[p]%mod;
		}
		else if(qf[p]==5)
		{
			admk[pp]=admk[pp-1],mulmk[pp]=mulmk[pp-1];
			if(qx[p]<0)ans=mo(ans+admk[pp]);
			else 
			{
				if(lstmk>=lst[qx[p]])ans=mo(ans+admk[pp]);
				else ans=mo(ans+mo((LL)mkx[qx[p]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod+mo(admk[pp]-(LL)admk[lst[qx[p]]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod)));
			}
		}
		else{
			admk[pp]=admk[pp-1],mulmk[pp]=mulmk[pp-1];ans=mo(ans+nowsum);}
	}
	write(ans);
	return 0;
}
posted @ 2020-06-10 18:50  echo6342  阅读(188)  评论(0编辑  收藏  举报