(私は実際には開始されませんが)まず第一に、これは地方選挙で問題をカットすることができます。
操作のすべてを見つけることは難しいことではありません実際には6つの事業、の分析は、どちらか一点の変更/照会され、いずれかの全体のシーケンスの変更/照会。そして、我々はすべて知っている、唯一の全体のシーケンスは、いくつかの美しい自然を操作します。
まず、我々は3つのマーク、維持\(追加\)、\ (MUL \)、\ (SUM \)を、加算、乗算マーク、およびシーケンス全体をマークしています。思考の木のラインに似ています。
まず、操作のシーケンス全体を考慮してください。
2は、オペレータのために、実際には、それがすることです\(追加\)マーカープラス\(ヴァル\) 、その後、\(SUM \)プラス\(ヴァル\ n回\)加算可換のは、明確に確立します。
動作3の場合、\(追加\)マーク、\(MUL \)マーク、\(SUM \)タグ\(\タイムズヴァル\) 、また真である分配法則に従って。
オペレータ4、無使用の割り当てを直接初期値に、標識された場合:\(= 0追加、MUL 1 = \) 、次いで\(ヴァル= SUM \ n回\) 。
操作6の場合、答えは明らかです\(SUM \) 。
今、各ポイントのために、操作の単一の点を考慮して(X- \)\、実際の重量はポイントではありません(A_X \)\、しかし(MUL * + A_X追加\)\時間を変更し、その後、意志明らかに直接操作を鉛の重みはありません(ヴァル\)\、しかし\(MUL \タイムズヴァル+追加\)私たちが代わりにすべきであると仮定することができるので、\(ヴァル「\)の要件を満たすために、そこに、\(ヴァル= MUL \回ヴァル'追加+は\) 、について解く= \ FRACアドインヴァル} {} {MUL \)\(ヴァル'、そう変更することができます。
動作の範囲は、単一の動作点、及びその逆を覆うことができるので、クエリが実際に、問題になる場合。この問題を解決するために、我々はこの時点では最終更新時刻を単一のポイントを記録するタイムスタンプ、および前回値が答えです後ろの人である間隔の変更を維持することがあります。
あなたも、さらに最適化を削減したい場合は50点の配列を直接使用することは、暴力のポイントを得ることができます。
入力フォーマット長くて退屈なことが、実際には業務の性質だけで実行注意\(Q \)抑えているヶ月が、あなたはハッシュテーブルを使用することができますので、ポイントが関与している可能性がある、数回繰り返し、毎回単一のハッシュテーブルで、その複雑さそうと直接クエリポイント変更/クエリ(N \)\は、単に問題ではない、と\(Q \)の関係、そしてこの質問はカットアップすることができます。
Tucao:Luoguの評価機は、遅すぎるLuoguますTLEに生きることができるlojで同じコードです。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<iostream>
#include<queue>
#include<cctype>
#include<ctime>
#include<unordered_map>
using namespace std;
#define A(x) cout << #x << " " << x << endl;
#define AA(x,y) cout << #x << " " << x << " " << #y << " " << y << endl;
#define AAA(x,y,z) cout << #x << " " << x << " " << #y << " " << y << " " << #z << " " << z << endl;
#define B cout << "Break" << endl;
#define ll long long
#define inf 1000000000
ll read()
{
char c = getchar();
ll x = 0,f = 1;
while(!isdigit(c))
{
if(c == '-') f = -1;
c = getchar();
}
while(isdigit(c))
{
x = x * 10 + c - '0';
c = getchar();
}
return f * x;
}
#define mod 10000019
ll add,mul = 1,sum,n,q,ans;
struct opt
{
ll tim,x,val;
}lst;
vector<opt>h[mod];
ll quick_pow(ll a,ll b)
{
ll ret = 1;
while(b)
{
if(b & 1) ret = ret * a % mod;
a = a * a % mod;
b >>= 1;
}
return ret;
}
ll query(ll x)
{
ll pos = x % mod;
for(int i = 0;i < h[pos].size();++i)
{
if(h[pos][i].x != x) continue;
if(h[pos][i].tim < lst.tim) return (mul * lst.val + add + mod) % mod;
else return (mul * h[pos][i].val + add + mod) % mod;
}
return (mul * lst.val + add + mod) % mod;
}
struct Query
{
ll op,x,val;
}qu[100010];
void push(ll x,ll val,ll tim)
{
ll pos = x % mod;
for(int i = 0;i < h[pos].size();++i)
{
if(h[pos][i].x == x)
{
h[pos][i].val = val,h[pos][i].tim = tim;
return;
}
}
h[pos].push_back({tim,x,val});
}
void calc(ll num,ll tim)
{
ll op = qu[num].op,x = qu[num].x,val = qu[num].val;
if(op == 1)
{
ll tp = query(x);
sum = (sum + val - tp + mod) % mod;
val = (val - add + mod) % mod * quick_pow(mul,mod - 2) % mod;
push(x,val,tim);
}
else if(op == 2)
{
add = ((add + val) % mod + mod) % mod;
sum = ((sum + val * n) % mod + mod) % mod;
}
else if(op == 3)
{
add = (add * val % mod + mod) % mod;
mul = (mul * val % mod + mod) % mod;
sum = (sum * val % mod + mod) % mod;
}
else if(op == 4)
{
lst.tim = tim,lst.val = val;
sum = val * n % mod;
add = 0,mul = 1;
}
else if(op == 5)
ans = (ans + query(qu[num].x) + mod) % mod;
else
ans = (ans + sum % mod + mod) % mod;
return;
}
ll a[100010],b[100010];
int main()
{
n = read(),q = read();
for(ll i = 1;i <= q;++i)
{
qu[i].op = read();
if(qu[i].op == 1) qu[i].x = read(),qu[i].val = read();
else if(qu[i].op <= 4) qu[i].val = read();
else if(qu[i].op == 5) qu[i].x = read();
qu[i].val = (qu[i].val % mod + mod) % mod;
}
ll t = read();
for(ll i = 1;i <= t;++i) a[i] = read(),b[i] = read();
for(ll i = 1;i <= t;++i)
{
for(ll j = 1;j <= q;++j)
{
ll num = ((a[i] + j * b[i]) % q + 1);
ll tim = (i - 1) * q + j;
calc(num,tim);
}
}
printf("%lld\n",(ans % mod + mod) % mod);
}