#include <bits/stdc++.h>
using namespace std;
using ll = long long;
static const int MOD = 1000000007;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
// shareMod[p]: số cổ phiếu của p (lưu mod MOD)
// cash_base[p]: số tiền p đang có (đã ghi nhận trước những sự kiện chưa rút) (mod MOD)
// lastG[p]: giá trị G tại lần cập nhật cuối của p
vector<int> shareMod(n+1, 0), cash_base(n+1, 0), lastG(n+1, 0);
int G = 0; // tích lũy "tiền cổ tức trên mỗi cổ phiếu" (mod MOD)
while(q--){
int type;
cin >> type;
if(type == 1){
int p;
long long x;
cin >> p >> x;
// 1) Đồng bộ tài khoản p với G (áp dụng cổ tức đang đọng)
int deltaG = (G - lastG[p] + MOD) % MOD;
// pending = shareMod[p] * deltaG mod
ll pend = ( (ll)shareMod[p] * deltaG ) % MOD;
cash_base[p] = (cash_base[p] + (int)pend) % MOD;
// 2) Cập nhật số cổ phiếu: shareMod[p] += x (x có thể âm)
int xmod = (int)((x % MOD + MOD) % MOD);
shareMod[p] = (shareMod[p] + xmod) % MOD;
// 3) Gán lại lastG[p] = G
lastG[p] = G;
}
else if(type == 2){
int v;
cin >> v;
// Chỉ việc cộng vào G
G = (G + v) % MOD;
}
else {
// type == 3
int p;
cin >> p;
// Tính tiền pending
int deltaG = (G - lastG[p] + MOD) % MOD;
ll pend = ( (ll)shareMod[p] * deltaG ) % MOD;
int total = (int)( (cash_base[p] + pend) % MOD );
// In ra kết quả
cout << total << "\n";
// Reset tài khoản p về 0
cash_base[p] = 0;
lastG[p] = G;
}
}
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnVzaW5nIGxsID0gbG9uZyBsb25nOwoKc3RhdGljIGNvbnN0IGludCBNT0QgPSAxMDAwMDAwMDA3OwoKaW50IG1haW4oKXsKICAgIGlvczo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsKICAgIGNpbi50aWUobnVsbHB0cik7CgogICAgaW50IG4sIHE7CiAgICBjaW4gPj4gbiA+PiBxOwoKICAgIC8vIHNoYXJlTW9kW3BdOiBz4buRIGPhu5UgcGhp4bq/dSBj4bunYSBwIChsxrB1IG1vZCBNT0QpCiAgICAvLyBjYXNoX2Jhc2VbcF06IHPhu5EgdGnhu4FuIHAgxJFhbmcgY8OzICjEkcOjIGdoaSBuaOG6rW4gdHLGsOG7m2Mgbmjhu69uZyBz4buxIGtp4buHbiBjaMawYSByw7p0KSAobW9kIE1PRCkKICAgIC8vIGxhc3RHW3BdOiBnacOhIHRy4buLIEcgdOG6oWkgbOG6p24gY+G6rXAgbmjhuq10IGN14buRaSBj4bunYSBwCiAgICB2ZWN0b3I8aW50PiBzaGFyZU1vZChuKzEsIDApLCBjYXNoX2Jhc2UobisxLCAwKSwgbGFzdEcobisxLCAwKTsKCiAgICBpbnQgRyA9IDA7ICAgLy8gdMOtY2ggbMWpeSAidGnhu4FuIGPhu5UgdOG7qWMgdHLDqm4gbeG7l2kgY+G7lSBwaGnhur91IiAobW9kIE1PRCkKCiAgICB3aGlsZShxLS0pewogICAgICAgIGludCB0eXBlOwogICAgICAgIGNpbiA+PiB0eXBlOwogICAgICAgIGlmKHR5cGUgPT0gMSl7CiAgICAgICAgICAgIGludCBwOwogICAgICAgICAgICBsb25nIGxvbmcgeDsKICAgICAgICAgICAgY2luID4+IHAgPj4geDsKICAgICAgICAgICAgLy8gMSkgxJDhu5NuZyBi4buZIHTDoGkga2hv4bqjbiBwIHbhu5tpIEcgKMOhcCBk4bulbmcgY+G7lSB04bupYyDEkWFuZyDEkeG7jW5nKQogICAgICAgICAgICBpbnQgZGVsdGFHID0gKEcgLSBsYXN0R1twXSArIE1PRCkgJSBNT0Q7CiAgICAgICAgICAgIC8vIHBlbmRpbmcgPSBzaGFyZU1vZFtwXSAqIGRlbHRhRyBtb2QKICAgICAgICAgICAgbGwgcGVuZCA9ICggKGxsKXNoYXJlTW9kW3BdICogZGVsdGFHICkgJSBNT0Q7CiAgICAgICAgICAgIGNhc2hfYmFzZVtwXSA9IChjYXNoX2Jhc2VbcF0gKyAoaW50KXBlbmQpICUgTU9EOwoKICAgICAgICAgICAgLy8gMikgQ+G6rXAgbmjhuq10IHPhu5EgY+G7lSBwaGnhur91OiBzaGFyZU1vZFtwXSArPSB4ICAoeCBjw7MgdGjhu4Mgw6JtKQogICAgICAgICAgICBpbnQgeG1vZCA9IChpbnQpKCh4ICUgTU9EICsgTU9EKSAlIE1PRCk7CiAgICAgICAgICAgIHNoYXJlTW9kW3BdID0gKHNoYXJlTW9kW3BdICsgeG1vZCkgJSBNT0Q7CgogICAgICAgICAgICAvLyAzKSBHw6FuIGzhuqFpIGxhc3RHW3BdID0gRwogICAgICAgICAgICBsYXN0R1twXSA9IEc7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYodHlwZSA9PSAyKXsKICAgICAgICAgICAgaW50IHY7CiAgICAgICAgICAgIGNpbiA+PiB2OwogICAgICAgICAgICAvLyBDaOG7iSB2aeG7h2MgY+G7mW5nIHbDoG8gRwogICAgICAgICAgICBHID0gKEcgKyB2KSAlIE1PRDsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIC8vIHR5cGUgPT0gMwogICAgICAgICAgICBpbnQgcDsKICAgICAgICAgICAgY2luID4+IHA7CiAgICAgICAgICAgIC8vIFTDrW5oIHRp4buBbiBwZW5kaW5nCiAgICAgICAgICAgIGludCBkZWx0YUcgPSAoRyAtIGxhc3RHW3BdICsgTU9EKSAlIE1PRDsKICAgICAgICAgICAgbGwgcGVuZCA9ICggKGxsKXNoYXJlTW9kW3BdICogZGVsdGFHICkgJSBNT0Q7CiAgICAgICAgICAgIGludCB0b3RhbCA9IChpbnQpKCAoY2FzaF9iYXNlW3BdICsgcGVuZCkgJSBNT0QgKTsKCiAgICAgICAgICAgIC8vIEluIHJhIGvhur90IHF14bqjCiAgICAgICAgICAgIGNvdXQgPDwgdG90YWwgPDwgIlxuIjsKCiAgICAgICAgICAgIC8vIFJlc2V0IHTDoGkga2hv4bqjbiBwIHbhu4EgMAogICAgICAgICAgICBjYXNoX2Jhc2VbcF0gPSAwOwogICAgICAgICAgICBsYXN0R1twXSA9IEc7CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiAwOwp9Cg==