ZOJ3765---Lights (Splay伸展树)

时间:2022-03-13 16:03:45

Lights


Time Limit: 8 Seconds      Memory Limit: 131072 KB

Now you have N lights in a line. Don't worry - the lights don't have color. The only status they have is on and off. And, each light has a value, too.

There is a boring student in ZJU. He decides to do some boring operations to the lights:

  1. L R status - Query the GCD (Greatest Common Divisor) of the value of the given status lights in range [LR]. For example, if now we have 3 lights which are {on, off and on}, and their value are {3, 5, 9}, then the GCD of the number of the lights on in [1, 3] is 3, and the lights off is 5.
  2. i value status - Add a light just behind to ith light. The initial status and the value is given also.
  3. i - Remove the ith light.
  4. i - If ith light is on, turn it off, else turn it on.
  5. i x - Modify the value of ith light to x.

Please help this boring guy to do this boring thing so that he can have time to find a girlfriend!

Input

The input contains multiple test cases. Notice there's no empty line between each test case.

For each test case, the first line of the a case contains two integers, N (1 ≤ N ≤ 200000) and Q (1 ≤ Q ≤ 100000), indicating the number of the lights at first and the number of the operations. In following N lines, each line contains two integers, Numi (1 ≤ Numi ≤ 1000000000) and Statusi (0 ≤ Statusi ≤ 1), indicating the number of the light i and the status of it. In following Q lines, each line indicating an operation, and the format is described above.

It is guaranteed that the range of the operations will be appropriate. For example, if there is only 10 lights, you will not receive an operation like "Q 1 11 0" or "D 11".

Output

For each Query operation, output an integer, which is the answer to the query. If no lights are with such status, please output -1.

Sample Input

3 12
27 1
32 0
9 1
Q 1 3 1
I 3 64 0
Q 2 4 0
Q 2 4 1
I 2 43 1
D 5
Q 1 2 1
M 1 35
Q 1 2 1
R 1
R 3
Q 1 2 1

Sample Output

9
32
9
27
35
-1

继续splay大法,熟练了之后 这种题就算是裸题了。。。 基本上都会用到 旋转 rotate, 伸展splay,获取第k的元素的位置 Get_kth,翻转reverse,删除delete函数。

这题因为数组开小TLE一上午,昨天晚上明明就已经是正确解法了,害我一直调试。

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 3e5+;
int siz[maxn],pre[maxn],ch[maxn][],st[maxn],s[maxn];
int key[maxn],GCD[][maxn];
int tot1,tot2,root,n,q;
int gcd(int x,int y)
{
return y == ? x : gcd (y,x % y);
}
void NewNode(int &r,int father,int k,int status)
{
if (tot2)
r = s[tot2--];
else
r = ++tot1;
pre[r] = father;
ch[r][] = ch[r][] = ;
st[r] = status;
key[r] = k;
siz[r] = ;
GCD[][r] = GCD[][r] = ;
GCD[st[r]][r] = k;
}
void push_up(int r)
{
siz[r] = siz[ch[r][]] + siz[ch[r][]] + ;
if (GCD[st[r]][r] == )
{
GCD[st[r]][r] = key[r];
}
GCD[][r] = gcd(GCD[][ch[r][]],GCD[][ch[r][]]);
GCD[][r] = gcd(GCD[][ch[r][]],GCD[][ch[r][]]);
GCD[st[r]][r] = gcd(GCD[st[r]][r],key[r]);
}
int A[maxn];
int B[maxn]; // A B 数组分别储存每个light的值以及状态
void build(int &x,int l,int r,int father)
{
if (l > r)
return;
int mid = (l + r) >> ;
NewNode(x,father,A[mid],B[mid]);
build(ch[x][],l,mid-,x);
build(ch[x][],mid+,r,x);
push_up(x);
}
void init()
{
root = tot1 = tot2 = ;
for (int i = ; i <= n; i++)
scanf ("%d%d",A+i,B+i);
NewNode(root,,,);
NewNode(ch[root][],root,,);
build(ch[ch[root][]][],,n,ch[root][]);
push_up(ch[root][]);
push_up(root);
}
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]][] == y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
push_up(y);
}
void Splay(int r,int goal)
{
while (pre[r] != goal)
{
if (pre[pre[r]] == goal)
{
Rotate(r,ch[pre[r]][] == r);
}
else
{
int y = pre[r];
int kind = (ch[pre[y]][] == y);
if (ch[y][kind] == r)
{
Rotate(y,!kind);
Rotate(r,!kind);
}
else
{
Rotate(r,kind);
Rotate(r,!kind);
}
}
}
push_up(r);
if (goal == )
root = r;
}
int Get_kth(int r,int k)
{
int t = siz[ch[r][]] + ;
if (k == t)
return r;
if (k > t)
return Get_kth(ch[r][],k-t);
else
return Get_kth(ch[r][],k);
}
void Insert(int pos,int val,int status)
{
Splay(Get_kth(root,pos+),);
Splay(Get_kth(root,pos+),root);
NewNode(ch[ch[root][]][],ch[root][],val,status);
push_up(ch[root][]);
push_up(root);
}
void eraser(int r)
{
if (!r)
return;
s[++tot2] = r;
eraser(ch[r][]);
eraser(ch[r][]);
}
void Delete(int pos)
{
Splay(Get_kth(root,pos),);
Splay(Get_kth(root,pos+),root);
eraser(ch[ch[root][]][]);
pre[ch[ch[root][]][]] = ;
ch[ch[root][]][] = ;
push_up(ch[root][]);
push_up(root);
}
void modify (int pos,int val)
{
Splay(Get_kth(root,pos),);
Splay(Get_kth(root,pos+),root);
int key_value = ch[ch[root][]][];
key[key_value] = val;
push_up(ch[ch[root][]][]);
push_up(ch[root][]);
push_up(root);
}
void reset(int pos)
{
Splay(Get_kth(root,pos),);
Splay(Get_kth(root,pos+),root);
int key_value = ch[ch[root][]][];
st[key_value] ^= ;
push_up(ch[ch[root][]][]);
push_up(ch[root][]);
push_up(root);
}
int query(int x,int y,int status)
{
Splay(Get_kth(root,x),);
Splay(Get_kth(root,y+),root);
push_up(ch[ch[root][]][]);
return GCD[status][ch[ch[root][]][]];
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif while (~scanf ("%d%d",&n,&q))
{
init();
for (int i = ; i < q; i++)
{
char op[];
scanf ("%s",op);
if (op[] == 'Q')
{
int x,y,z;
scanf ("%d%d%d",&x,&y,&z);
int ans = query(x,y,z);
printf("%d\n",ans > ? ans : -);
}
if (op[] == 'I')
{
int x,z,y;
scanf ("%d%d%d",&x,&y,&z);
Insert(x,y,z);
}
if (op[] == 'D')
{
int x;
scanf ("%d",&x);
Delete(x);
}
if (op[] == 'M')
{
int x, z;
scanf ("%d%d",&x,&z);
modify(x,z);
}
if (op[] == 'R')
{
int x;
scanf ("%d",&x);
reset(x);
}
}
}
return ;
}