[SCOI2013]多项式的运算
嘟嘟嘟
半年不写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
#include
#include
#include
#include
#include
#include
#include
#include
#include
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\n", 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;
}
转载于:https://www.cnblogs.com/mrclr/p/10479094.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
