嘟嘟嘟
半年不寫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\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
總結
以上是生活随笔為你收集整理的[SCOI2013]多项式的运算的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。