您的位置:首页 > 其它

[ZOJ 3765 Lights] Splay

2017-04-21 13:18 232 查看

[ZOJ 3765 Lights] Splay

分类:
Data Structure
Splay


1. 题目链接

[ZOJ 3765 Lights]

2. 题意描述

有一个长度为n的序列。q次操作。

序列中每个元素有两个属性,value和status。有以下几种操作。

查询区间[L,R]范围内状态为status的数的value的gcd;

第i个元素后面插入一个元素

删除第i个元素

将第i个元素的status取反

修改第i个元素的value

数据范围:(1≤N≤200000,1≤Q≤100000),(1≤value≤109,0≤status≤1)

3. 解题思路

裸的Splay模板。只需要维护value以及区间状态status为0,1的gcd0,gcd1即可。

注意一下,后面的操作中,会生成一些节点,所以要降数组大小开到300000。

试了一下单旋和双旋,在这个题目里面没有什么区别。

不过,正式比赛的时候千万不要这么zuo,在链式的情况下,单旋之后依旧会是一条链,而双旋之后,链会变成一棵树。只有双旋,才能保证均摊复杂度为O(log2n)

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LB;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef vector<int> VI;

const int INF = 0x3f3f3f3f;
const LL INFL = 0x3f3f3f3f3f3f3f3fLL;
const double eps = 1e-8;
const double PI = acos(-1.0);

#define Key_value ch[ch[root][1]][0]
const int MAXN = 300010;
int pre[MAXN], ch[MAXN][2], sz[MAXN];
int root, tot1;
int gcd[MAXN][2], stat[MAXN], key[MAXN];
int s[MAXN], tot2; //内存池和容量
int a[MAXN], b[MAXN];

int n, q;
//debug部分**********************************
void Treavel(int x) {
if(x) {
Treavel(ch[x][0]);
printf("root: %2d: lch %2d rch %2d fa %2d size= %2d\n", x, ch[x][0], ch[x][1], pre[x], sz[x]);
Treavel(ch[x][1]);
}
}
void debug() {
printf("root:%d\n", root);
Treavel(root);
}
//以上是debug部分**************************************

inline void NewNode(int &r, const int& father, const int& ax, const int& bx) {
if(tot2) r = s[tot2--]; //取的时候是tot2--,存的时候就是++tot2
else r = ++tot1;
pre[r] = father;
ch[r][0] = ch[r][1] = 0;

key[r] = ax;
stat[r] = bx;

gcd[r][bx] = ax;
gcd[r][!bx] = 0;

sz[r] = 1;
}

inline int m_gcd(const int& ax, const int& bx) {
if(ax == 0 && bx == 0) return 0;
if(ax == 0) return bx;
if(bx == 0) return ax;
return __gcd(ax, bx);
}

inline void pushUp(const int&r) {
int lson = ch[r][0], rson = ch[r][1];
sz[r] = sz[lson] + sz[rson] + 1;

gcd[r][0] = gcd[r][1] = 0;
gcd[r][0] = m_gcd(gcd[lson][0], gcd[rson][0]);
gcd[r][1] = m_gcd(gcd[lson][1], gcd[rson][1]);
gcd[r][stat[r]] = m_gcd(gcd[r][stat[r]], key[r]);
}

void Build(int &x, int l, int r, int father) {
if(l > r) return;
int mid = (l + r) / 2;
NewNode(x, father, a[mid], b[mid]);
Build(ch[x][0], l, mid - 1, x);
Build(ch[x][1], mid + 1, r, x);
pushUp(x);
}

void Init() {
root = tot1 = tot2 = 0;
ch[root][0] = ch[root][1] = sz[root] = pre[root] = 0;
stat[0] = gcd[root][0] = gcd[root][1] = key[root] = 0;

NewNode(root, 0, 0, 0);
NewNode(ch[root][1], root, 0, 0);
for(int i = 0; i < n; i++)
scanf("%d %d", &a[i], &b[i]);
Build(Key_value, 0, n - 1, ch[root][1]);
pushUp(ch[root][1]);
pushUp(root);
}
//旋转,0为左旋,1为右旋
void Rotate(int x, int kind) {
int y = pre[x];
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
pushUp(y);
}

// 将r放到goal下面,, 双旋
void Splay(int r, int goal) {
while(pre[r] != goal) {
if(pre[pre[r]] == goal) {
Rotate(r, ch[pre[r]][0] == r);
} else {
int y = pre[r];
int kind = ch[pre[y]][0] == y;
if(ch[y][kind] == r) {
//zig-zag zag-zig
Rotate(r, !kind);
Rotate(r, kind);
} else {
//zig-zig zag-zag
Rotate(y, kind);
Rotate(r, kind);
}
}
}
pushUp(r);
if(goal == 0) root = r;
}
// 将r放到goal下面,, 单旋
/*
void Splay(int r, int goal) {
while(pre[r] != goal) {
Rotate(r, ch[pre[r]][0] == r);
}
pushUp(r);
if(goal == 0) root = r;
}
*/
int Kth(int r, int k) {
int t = sz[ch[r][0]] + 1;
if(t == k) return r;
if(t > k) return Kth(ch[r][0], k);
else return Kth(ch[r][1], k - t);
}

void Insert(int pos, int ax, int bx) {
Splay(Kth(root, pos + 1), 0);
Splay(Kth(root, pos + 2), root);
NewNode(Key_value, ch[root][1], ax, bx);
pushUp(ch[root][1]);
pushUp(root);
}

void erase(int r) {
if(!r)return;
s[++tot2] = r;
erase(ch[r][0]);
erase(ch[r][1]);
}

void Delete(int pos) {
Splay(Kth(root, pos), 0);
Splay(Kth(root, pos + 2), root);
erase(Key_value);
pre[Key_value] = 0;
Key_value = 0;
pushUp(ch[root][1]);
pushUp(root);
}

void Update_R(int pos) {
Splay(Kth(root, pos), 0);
Splay(Kth(root, pos + 2), root);
stat[Key_value] ^= 1;
pushUp(Key_value);
pushUp(ch[root][1]);
pushUp(root);
}

void Update_M(int pos, int a) {
Splay(Kth(root, pos), 0);
Splay(Kth(root, pos + 2), root);
key[Key_value] = a;
pushUp(Key_value);
pushUp(ch[root][1]);
pushUp(root);
}

int Get_Ans(int L, int R, int bx) {
Splay(Kth(root, L), 0);
Splay(Kth(root, R + 2), root);
return gcd[Key_value][bx];
}

int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
int L, R, ax, bx, px, ans;
char op[10];
while(scanf("%d %d", &n, &q) == 2) {
Init();
// debug();
while(q --) {
scanf("%s", op);
if(op[0] == 'Q') {
scanf("%d %d %d", &L, &R, &bx);
ans = Get_Ans(L, R, bx);
printf("%d\n", ans ? ans : -1);
} else if(op[0] == 'I') {
scanf("%d %d %d", &px, &ax, &bx);
Insert(px, ax, bx);
} else if(op[0] == 'D') {
scanf("%d", &px);
Delete(px);
} else if(op[0] == 'R') {
scanf("%d", &px);
Update_R(px);
} else if(op[0] == 'M') {
scanf("%d %d", &px, &ax);
Update_M(px, ax);
}
}
}

#ifdef ___LOCAL_WONZY___
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // ___LOCAL_WONZY___
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: