Can you answer these queries VIII 【SPOJ - GSS8】【Splay】

题目链接


  题意:有N个(无符号整型)数,我们有如下的四种操作:

(一)、插入一个数;

(二)、删除某个位置上的数;

(三)、把某个位置上的数换成一个数;

(四)、查询这个区间上的,其中,0 ≤ K ≤ 10。

  然后看到这个(2^32)很容易想到unsigned int刚好也是自然溢出的32位int。然后我们就可以利用unsigned int来避免取模了。

  再后来,前三个问题好解,但是问题四,我们就要去想到pushup()里面应该怎么去改。

  那么,我们就可以预处理1~MaxN各自的0~10次幂a[ i ][ j ],那么在这里是不是就把a[ mid - l + 1 ][ k - j ]就可以求出来了,然后我们就要去求rans的j次幂刚好就是在Splay的结构体里存好的了。所以每个pushup()的时间复杂度就是O(k)。

  然后剩余的就是Splay的模板了。

4
1 2 3 5
7
Q 0 2 0
I 3 4
Q 2 4 1
D 0
Q 0 3 1
R 1 2
Q 0 1 0
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, Q, root, cal[12][12], tot;
uit  a[maxN][12], ww[maxN];
struct node
{
    int ff, siz, ch[2];
    uit val[11], here;
    node() { ff = siz = ch[0] = ch[1] = here = 0; memset(val, 0, sizeof(val)); }
}t[maxN];
inline void pushup(int rt)
{
    int lc = t[rt].ch[0], rc = t[rt].ch[1];
    t[rt].siz = t[lc].siz + t[rc].siz + 1;
    for(int i=0; i<=10; i++)
    {
        t[rt].val[i] = t[lc].val[i] + t[rt].here * a[t[lc].siz + 1][i];
        for(int j=0; j<=i; j++) t[rt].val[i] += cal[i][j] * a[t[lc].siz + 1][i - j] * t[rc].val[j];
    }
}
void buildSplay(int rt, int l, int r)
{
    if(l > r) return;
    int mid = HalF;
    t[rt].ch[mid > rt] = mid;
    t[mid].ff = rt;
    t[mid].siz = 1;
    t[mid].here = ww[mid];
    if(l == r)
    {
        for(int i=0; i<=10; i++) t[mid].val[i] = ww[mid];
        return;
    }
    buildSplay(mid, l, mid - 1);
    buildSplay(mid, mid + 1, r);
    t[mid].siz = t[t[mid].ch[0]].siz + t[t[mid].ch[1]].siz + 1;
    pushup(mid);
}
inline void Rotate(int x)
{
    int y = t[x].ff, z = t[y].ff, k = t[y].ch[1] == x;
    t[z].ch[t[z].ch[1] == y] = x;
    t[x].ff = z;
    t[y].ch[k] = t[x].ch[k^1];
    t[t[x].ch[k^1]].ff = y;
    t[x].ch[k^1] = y;
    t[y].ff = x;
    pushup(y); pushup(x);
}
inline void Splay(int x, int goal)
{
    while (t[x].ff != goal)
    {
        int y = t[x].ff, z = t[y].ff;
        if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? Rotate(x) : Rotate(y);
        Rotate(x);
    }
    if(!goal) root = x;
}
inline int Kth(int x)
{
    int u = root;
    if(x > t[u].siz) return -1;
    while(true)
    {
        int y = t[u].ch[0];
        if(x > t[y].siz + 1)
        {
            x -= t[y].siz + 1;
            u = t[u].ch[1];
        }
        else
        {
            if(t[y].siz >= x) u = y;
            else return u;
        }
    }
}
inline void Insert(int x, int y)
{
    int las = Kth(x), nex = Kth(x + 1);
    Splay(las, 0); Splay(nex, las);
    t[nex].ch[0] = ++tot;
    t[tot].ff = nex;
    t[tot].siz = 1;
    t[tot].here = y;
    for(int i=0; i<=10; i++) t[tot].val[i] = y;
    pushup(nex); pushup(las);
}
inline void Delet(int x)
{
    int las = Kth(x - 1), nex = Kth(x + 1);
    Splay(las, 0); Splay(nex, las);
    t[nex].ch[0] = 0;
    pushup(nex); pushup(las);
}
inline void re_set(int x, int y)
{
    int now = Kth(x);
    Splay(now, 0);
    t[now].here = y;
    pushup(now);
}
inline int query(int x, int y, int k)
{
    int las = Kth(x - 1), nex = Kth(y + 1);
    Splay(las, 0); Splay(nex, las);
    return t[t[nex].ch[0]].val[k];
}
inline void pre_Cal()   //求出C(i, j)
{
    for(int i=0; i<=10; i++) cal[i][0] = 1;
    cal[1][1] = 1;
    for(int i=2; i<=10; i++)
    {
        for(int j=1; j<=i; j++)
        {
            cal[i][j] = cal[i-1][j] + cal[i-1][j-1];
        }
    }
}
inline void init()
{
    for(int i=1; i<maxN; i++)
    {
        a[i][0] = 1;
        for(int k=1; k<=10; k++)
        {
            a[i][k] = a[i][k-1] * i;
        }
    }
}
int main()
{
    pre_Cal();
    scanf("%d", &N);
    init();
    for(int i=2; i<=N + 1; i++) scanf("%u", &ww[i]);
    ww[1] = ww[N + 2] = 0;
    buildSplay(0, 1, N + 2);
    t[0].siz = t[0].ff = t[0].here = t[0].ch[0] = t[0].ch[1] = 0; memset(t[0].val, 0, sizeof(t[0].val));
    root = (N + 3)>>1;
    tot = N + 2;
    scanf("%d", &Q);
    char op[3]; int x, y, k;
    while(Q--)
    {
        scanf("%s", op);
        if(op[0] == 'I')    //在x+1~x+2中间插入个数y
        {
            scanf("%d%d", &x, &y); x++;
            Insert(x, y);
        }
        else if(op[0] == 'D')   //删除第x+2个数
        {
            scanf("%d", &x); x += 2;
            Delet(x);
        }
        else if(op[0] == 'R')   //把第i+2个数变成y
        {
            scanf("%d%d", &x, &y); x += 2;
            re_set(x, y);
        }
        else    //查询
        {
            scanf("%d%d%d", &x, &y, &k); x+=2; y+=2;
            uit tmp = query(x, y, k);
            //if(tmp < 0) tmp += _UP;
            printf("%u\n", tmp);
        }
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值