P5358 [SDOI2019]快速查询

传送门

做法:

记全体加法标记,全体乘法标记,数值总和 为 \(qa,qm,sum\),单个修改用 \(map\) 存。

操作一:将其数值赋为 \((x-qa)/qm\),修改 \(sum\)。(需预处理逆元)。

操作二:修改 \(qa\),\(sum\)。

操作三:修改 \(qa\),\(qm\),\(sum\)。

操作四:\(qa=x,qm=0\)。

操作五:找到 map 里的值乘上 qm 再加上 qa。

code:

#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
const int N=5e5+8;
const ll mod=1e7+19;
int n,q,t;
ll a[100005][5];
map<int,ll> pp;
ll qa,qm;
ll sum;
ll ans=0;
ll inv[mod];
ll ck(int x)
{
	if(pp.find(x)==pp.end()) return qa%mod;
	else return (pp[x]*qm%mod+qa)%mod;
}
void work(int k)
{
	if(a[k][0]==1)	{
		sum=(sum-ck(a[k][1])+mod)%mod;
		pp[a[k][1]]=(a[k][2]-qa+mod)*inv[qm]%mod;
		sum+=a[k][2];sum%=mod;
	}
	else if(a[k][0]==2) {
		qa+=a[k][1];
		qa%=mod;
		sum+=(ll)n*a[k][1]%mod;
		sum%=mod;
	}
	else if(a[k][0]==3){
		qm=qm*a[k][1]%mod;
		qa=qa*a[k][1]%mod;
		sum=sum*a[k][1]%mod;
	}
	else if(a[k][0]==4){
		sum=(ll)n*a[k][1]%mod;
		qm=1,qa=a[k][1];
		pp.clear();
	}
	else if(a[k][0]==5){
		ans+=ck(a[k][1]);ans%=mod;
	}
	else ans+=sum,ans%=mod;
}
signed main()
{
	inv[1]=1;
	for(int i=2;i<mod;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; //线性预处理逆元 
	cin>>n;cin>>q;
	for(int i=1;i<=q;i++)
	{
		scanf("%lld",&a[i][0]);
		if(a[i][0]<6) scanf("%lld",&a[i][1]);
		if(a[i][0]==1) scanf("%lld",&a[i][2]),a[i][2]=(a[i][2]%mod+mod)%mod; 
		else if(a[i][0]<=4) a[i][1]=(a[i][1]%mod+mod)%mod;
		if(a[i][0]==3&&!a[i][1]) a[i][0]=4;
	}
	cin>>t;
	while(t--)
	{
		ll a,b;
		scanf("%lld%lld",&a,&b);
		for(int i=1;i<=q;i++)
		work((a+i*b)%q+1);
	}
	cout<<(ans%mod+mod)%mod<<endl;
 } 
上一篇:Apache doris stream load任务导致大量任务堆积结束不了的问题


下一篇:[746] Interlude Update 3