嘟嘟嘟
半年不写splay,一写就半年……
辛亏我长精神头复习了一下,要不然考场上遇到平衡树的题肯定废了。
这道题,无非就让你求这么几个事儿:
1.区间加。
2.区间乘。
3.区间向后移一位。
4.代数求和。
对于查询操作,因为最多不超过10次,所以单次(O(nlogn))暴力就好了。
前两个操作不说了。
对于第三个操作,要动一点脑子:相当于把第(L)位清零,([L + 1, R - 1])向右移一位,最后第(R + 1)位加上第(R)位的值。
于是我一直在想,怎么实现区间平移的操作。后来发现只要在(L)之前插入一个权值为0的节点就完事了,同时处理了清零和平移一位的操作。
然后就是单点加和删除节点了。
不过第三个操作整体很坑。细节比较麻烦:插入完节点后,第(R)位就变成了第(R + 1)位,所以应该删的是(R + 1),不是(R)。
代码中懒得写垃圾回收了,索性开了二倍的空间。
然后因为没有告诉最高次项,所以又开了个变量Max维护最高次。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e5 + 5;
const ll mod = 20130426;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
char s[10];
int n, Max = 0;
struct Tree
{
int ch[2], fa, siz;
ll val, add, mul;
}t[maxn << 1];
int root, tcnt = 0;
In ll mul(ll a, ll b) {return a * b % mod;}
In ll inc(ll a, ll b) {return a + b >= mod ? a + b - mod : a + b;}
In ll quickpow(ll a, ll b)
{
ll ret = 1;
for(; b; b >>= 1, a = a * a % mod)
if(b & 1) ret = ret * a % mod;
return ret;
}
In void c_mul(int now, ll d)
{
t[now].val = mul(t[now].val, d);
t[now].mul = mul(t[now].mul, d); t[now].add = mul(t[now].add, d);
}
In void c_add(int now, ll d)
{
t[now].val = inc(t[now].val, d);
t[now].add = inc(t[now].add, d);
}
In void pushdown(int now)
{
if(t[now].mul ^ 1)
{
if(t[now].ch[0]) c_mul(t[now].ch[0], t[now].mul);
if(t[now].ch[1]) c_mul(t[now].ch[1], t[now].mul);
t[now].mul = 1;
}
if(t[now].add)
{
if(t[now].ch[0]) c_add(t[now].ch[0], t[now].add);
if(t[now].ch[1]) c_add(t[now].ch[1], t[now].add);
t[now].add = 0;
}
}
In void pushup(int now)
{
t[now].siz = t[t[now].ch[0]].siz + t[t[now].ch[1]].siz + 1;
}
In void rotate(int x)
{
int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x);
t[z].ch[t[z].ch[1] == y] = x, t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1], t[t[y].ch[k]].fa = y;
t[x].ch[k ^ 1] = y, t[y].fa = x;
pushup(y), pushup(x);
}
In void splay(int x, int s)
{
while(t[x].fa ^ s)
{
int y = t[x].fa, z = t[y].fa;
if(z ^ s) rotate(((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) ? x : y);
rotate(x);
}
if(!s) root = x;
}
In void _PrintTr(int now)
{
if(!now) return;
pushdown(now);
printf("now:%d val:%lld ls:%d rs:%d
", now, t[now].val, t[now].ch[0], t[now].ch[1]);
_PrintTr(t[now].ch[0]), _PrintTr(t[now].ch[1]);
}
In int build(int L, int R, int _f)
{
if(L > R) return 0;
int mid = (L + R) >> 1, now = ++tcnt;
if(_f) t[now].fa = _f;
t[now].siz = 1;
t[now].val = (mid == 1 || mid == maxn - 2) ? -INF : 0;
t[now].add = 0, t[now].mul = 1;
t[now].ch[0] = build(L, mid - 1, now);
t[now].ch[1] = build(mid + 1, R, now);
pushup(now);
return now;
}
In int find(int k)
{
int now = root;
while("ACAC!")
{
pushdown(now);
if(t[t[now].ch[0]].siz >= k) now = t[now].ch[0];
else if(t[t[now].ch[0]].siz + 1 == k) return now;
else k -= (t[t[now].ch[0]].siz + 1), now = t[now].ch[1];
}
}
In void split(int L, int R)
{
int a = find(L), b = find(R + 2);
splay(a, 0), splay(b, a);
pushdown(root), pushdown(t[root].ch[1]);
}
In void change(int L, int R)
{
int a = find(L), b = find(L + 1);
splay(a, 0), splay(b, a);
pushdown(root), pushdown(t[root].ch[1]);
int now = t[root].ch[1], p = ++tcnt;
t[now].ch[0] = p;
t[p].fa = now, t[p].siz = 1;
t[p].add = t[p].val = 0, t[p].mul = 1;
splay(p, 0);
split(R + 1, R + 1);
now = t[root].ch[1], p = t[now].ch[0];
t[now].val = inc(t[now].val, t[p].val);
--t[now].siz;
t[now].ch[0] = 0, t[p].fa = 0;
splay(now, 0);
}
In ll query(int x)
{
int a = find(x + 1); splay(a, 0);
return t[root].val;
}
int main()
{
// freopen("ha.in", "r", stdin);
// freopen("ha.out", "w", stdout);
n = read();
root = build(1, maxn - 2, 0);
for(int i = 1; i <= n; ++i)
{
scanf("%s", s);
if(s[3] == 'x')
{
int L = read() + 1, R = read() + 1;
change(L, R);
Max = max(Max, R + 1);
}
else if(s[0] == 'a')
{
int L = read() + 1, R = read() + 1, d = read();
Max = max(Max, R);
split(L, R), c_add(t[t[root].ch[1]].ch[0], d);
}
else if(s[0] == 'm')
{
int L = read() + 1, R = read() + 1, d = read();
Max = max(Max, R);
split(L, R), c_mul(t[t[root].ch[1]].ch[0], d);
}
else
{
ll d = read(), ans = 0;
for(int j = 1; j <= Max; ++j)
ans = inc(ans, mul(query(j), quickpow(d, j - 1)));
write(ans), enter;
}
}
return 0;
}