非常裸的一棵Splay树,需要询问的是区间gcd,但是区间上每个数分成了两种状态,做的时候分别存在val[2]的数组里就好。区间gcd的时候基本上不支持区间的操作了吧。。不然你一个区间里加一个数gcd都不知道怎么维护了,所以维护点的gcd是比较简单的,题目存在删除和增加,所以Splay树无误了。删除一个结点或区间的方法是先把它get出来,然后令root->ch[1]->ch[0]=null,记得每次操作完要提根。

#pragma warning(disable:4996)
#include<cstring>
#include<string>
#include<cstdio>
#include<iostream>
#define ll long long
#define maxn 401000
using namespace std; int n, q; int gcd(int a, int b)
{
while (a&&b) { a %= b; a ^= b; b ^= a; a ^= b; }
return a + b;
} struct Node
{
Node *ch[2], *p;
int size, val[2], gval[2];
int status;
Node(){
size = 0; val[0] = val[1] = 0; status = 0; gval[0] = gval[1] = 0;
}
bool d() {
return this == p->ch[1];
}
void setc(Node *c, int d){
ch[d] = c; c->p = this;
}
void cvalIt(int cval){
val[status] = cval;
gval[status] = gcd(val[status],gcd(ch[0]->gval[status], ch[1]->gval[status]));
}
void cstaIt(){
swap(val[status ^ 1], val[status]);
gval[status] = gcd(ch[0]->gval[status], ch[1]->gval[status]);
gval[status ^ 1] = gcd(gval[status ^ 1], gcd(ch[0]->gval[status ^ 1], ch[1]->gval[status ^ 1]));
status ^= 1;
}
void upd(){
size = ch[0]->size + ch[1]->size + 1;
for (int i = 0; i < 2; i++){
gval[i] = gcd(gcd(ch[0]->gval[i], ch[1]->gval[i]), val[i]);
}
}
}Tnull,*null=&Tnull; Node mem[maxn], *C = mem; Node*make(int v, int sta){
C->ch[0] = C->ch[1] = null;
C->size = 1;
C->val[sta] = v; C->val[sta ^ 1] = 0;
C->gval[sta] = v; C->gval[sta ^ 1] = 0;
C->status = sta;
return C++;
} int ax[maxn], bx[maxn]; Node*build(int l, int r)
{
if (l >= r) return null;
int m = (l + r) >> 1;
Node *t = make(ax[m], bx[m]);
t->setc(build(l, m), 0);
t->setc(build(m + 1, r), 1);
t->upd();
return t;
} Node *root;
void rot(Node*t) {
Node*p = t->p;
//p->relax();
//t->relax();
int d = t->d();
p->p->setc(t, p->d());
p->setc(t->ch[!d], d);
t->setc(p, !d);
p->upd();
if (p == root)
root = t;
} void splay(Node*t, Node*f = null) {
while (t->p != f) {
if (t->p->p == f)
rot(t);
else
t->d() == t->p->d() ? (rot(t->p), rot(t)) : (rot(t), rot(t));
}
t->upd();
} Node* select(int k) {
for (Node*t = root;;) {
//t->relax();
int c = t->ch[0]->size;
if (k == c)
return t;
if (k > c)
k -= c + 1, t = t->ch[1];
else
t = t->ch[0];
}
} Node*&get(int l, int r) { //[l,r)
Node*L = select(l - 1);
Node*R = select(r);
splay(L);
splay(R, L);
return R->ch[0];
} void print(Node* x)
{
if (x == null) return;
print(x->ch[0]);
printf(" %d", x->val[0]);
print(x->ch[1]);
} int main()
{
while (~scanf("%d%d", &n, &q))
{
for (int i = 1; i <= n; i++){
scanf("%d%d", &ax[i], &bx[i]);
}
C = mem;
ax[0] = ax[n + 1] = 0; bx[0] = bx[n + 1] = 0;
root = build(0, n + 2); root->p = null;
char type[3];
int li, ri, si,vi;
for (int i = 0; i < q; i++){
scanf("%s", type);
if (type[0] == 'Q'){
scanf("%d%d%d", &li, &ri, &si);
Node* &t=get(li, ri+1);
if (t->gval[si]) {
printf("%d\n", t->gval[si]);
}
else puts("-1");
}
else if (type[0] == 'I'){
scanf("%d%d%d", &li, &vi, &si);
Node *&t = get(li, li + 1);
t->ch[1] = make(vi, si);
splay(t);
}
else if (type[0] == 'D' ){
scanf("%d", &li);
Node *&t = get(li, li+1);
root->ch[1]->ch[0] = null;
splay(root->ch[1]);
}
else if (type[0] == 'R'){
scanf("%d", &li);
Node *&t = get(li, li + 1);
t->cstaIt();
splay(t);
}
else if (type[0] == 'M'){
scanf("%d%d", &li, &vi);
Node *&t = get(li, li + 1);
t->cvalIt(vi);
splay(t);
}
}
}
return 0;
}

ZOJ3765 Lights Splay树的更多相关文章

  1. Splay树-Codevs 1296 营业额统计

    Codevs 1296 营业额统计 题目描述 Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司 ...

  2. Splay树再学习

    队友最近可能在学Splay,然后让我敲下HDU1754的题,其实是很裸的一个线段树,不过用下Splay也无妨,他说他双旋超时,单旋过了,所以我就敲来看下.但是之前写的那个Splay越发的觉得不能看,所 ...

  3. 暑假学习日记:Splay树

    从昨天开始我就想学这个伸展树了,今天花了一个上午2个多小时加下午2个多小时,学习了一下伸展树(Splay树),学习的时候主要是看别人博客啦~发现下面这个博客挺不错的http://zakir.is-pr ...

  4. 1439. Battle with You-Know-Who(splay树)

    1439 路漫漫其修远兮~ 手抄一枚splay树 长长的模版.. 关于spaly树的讲解   网上很多随手贴一篇 貌似这题可以用什么bst啦 堆啦 平衡树啦 等等 这些本质都是有共同点的 查找.删除特 ...

  5. 伸展树(Splay树)的简要操作

    伸展树(splay树),是二叉排序树的一种.[两个月之前写过,今天突然想写个博客...] 伸展树和一般的二叉排序树不同的是,在每次执行完插入.查询.删除等操作后,都会自动平衡这棵树.(说是自动,也就是 ...

  6. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  7. hdu 3436 splay树+离散化*

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  8. hdu 1890 splay树

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tot ...

  9. hdu3487 splay树

    Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

随机推荐

  1. C++虐恋:MBCS安装失败导致的四天误工

    情况描述:接收远程队友的C++代码,基于vc120工具集(VS2013),而我的机器上是VS2015,需要安装VS2013(只选MFC,除主程序与MFC外其余的组件全部卸掉).然后开始编译,提示 MS ...

  2. c语言 char*类型作为中间变量将许多字符串保存到一个数组的问题

    char*是一个字符串指针,如下面的程序value_作为一个中间变量用来在for循环中scanf输入的值的接收者,然后将value_保存到array中,但是一下程序会出现一个问题就是当你跳出这个函数时 ...

  3. 隐藏虚拟键盘,解决键盘挡住UITextField问题

    再正式开始之前,先来介绍一下IOS的键盘类型: 一.键盘风格 UIKit框架支持8种风格键盘 ? 1 2 3 4 5 6 7 8 9 10 typedef enum {      UIKeyboard ...

  4. 模拟抛硬币(C语言实现)

    实现代码: #include<stdio.h> #include<stdlib.h> int heads() { ; } int main(int argc, char *ar ...

  5. 【Qt】Qt之自定义界面(右下角冒泡)【转】

    简述 网页右下角上经常会出现一些提示性的信息,桌面软件中也比较常见,类似360新闻.QQ消息提示一样! 这种功能用动画实现起来很简单,这节我们暂时使用定时器来实现,后面章节会对动画框架进行详细讲解. ...

  6. jquery插件formValidator的ajaxValidator传参数问题

    最近在用formValidator插件,遇到一个问题.当我想用ajaxValidator的url传参数时,$("#tbName").val().document.getElemen ...

  7. TCP HelloWord

    client.cpp #include <stdio.h> #include <winsock2.h> #pragma comment (lib,"ws2_32&qu ...

  8. python的各种推导式(列表推导式、字典推导式、集合推导式)

    推导式comprehensions(又称解析式),是Python的一种独有特性.推导式是可以从一个数据序列构建另一个新的数据序列的结构体. 共有三种推导,在Python2和3中都有支持: 列表(lis ...

  9. java之classpath到底是什么

    如果你输入一个命令,比如java那么系统是如何找到这个命令的呢?按照顺序,系统先在当前目录搜索是否有java.exe, java.bat 等. 如果没有,就得到系统的PATH(不区分大小写)里面查找. ...

  10. UIWebView 需改userAgent 并且加载微信公共账号

    需要注意的是需要获取原来的UIWebView的User-Agent,然后拼接上自己新的User-Agent,貌似直接替换原来的无效,另外,修改User-Agent之后重新创建UIWebView加载网页 ...