线段树入门题,换成splay tree 来搞搞。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;#define MAXN 200100long long Add[MAXN];//延迟标记struct Splay_Tree
{int cnt, rt;//cnt为节点数,rt == rootstruct Tree{long long K;long long sumk;int key;//关键字int num, size;//num是这个节点有多少重复,size是以这个节点为根的子树大小。int fa, son[2];}T[MAXN];inline void init(){cnt = 0;//初始化超级根节点(标记为0的节点)T[0].size = 0;T[0].sumk = 0;T[0].K = 0;rt = 0;memset(Add,0,sizeof(Add));}inline void PushUp(int x){T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+T[x].num;T[x].sumk=T[T[x].son[0]].sumk+T[T[x].son[1]].sumk+T[x].K;}inline void PushDown(int x){if(Add[x]){if(T[x].son[0])//
            {T[T[x].son[0]].K += Add[x];T[T[x].son[0]].sumk += T[T[x].son[0]].size*Add[x];Add[T[x].son[0]]+=Add[x];}if(T[x].son[1]){T[T[x].son[1]].K+=Add[x];T[T[x].son[1]].sumk += T[T[x].son[1]].size*Add[x];Add[T[x].son[1]]+=Add[x];}Add[x]=0;//不管子节点有没有,这层一定往下推,没有子节点相当于标记无效。
        }}inline int Newnode(int key, int fa,int K) //新建一个节点并返回
    {++cnt;T[cnt].K = T[cnt].sumk = K;T[cnt].key=key;T[cnt].num=T[cnt].size=1;T[cnt].fa=fa;T[cnt].son[0]=T[cnt].son[1]=0;return cnt;}inline void Rotate(int x, int p) //0左旋 1右旋
    {int y=T[x].fa;PushDown(y);//这里是不是必须的,我感觉从小往上不需要往上推
        PushDown(x);T[y].son[!p]=T[x].son[p];T[T[x].son[p]].fa=y;T[x].fa=T[y].fa;if(T[x].fa)T[T[x].fa].son[T[T[x].fa].son[1] == y]=x;T[x].son[p]=y;T[y].fa=x;PushUp(y);PushUp(x);}void Splay(int x, int To) //将x节点移动到To的子节点中
    {while(T[x].fa != To){if(T[T[x].fa].fa == To)Rotate(x, T[T[x].fa].son[0] == x);else{int y=T[x].fa, z=T[y].fa;int p=(T[z].son[0] == y);if(T[y].son[p] == x)Rotate(x, !p), Rotate(x, p); //之字旋elseRotate(y, p), Rotate(x, p); //一字旋
            }}if(To == 0) rt=x;}int GetPth(int p, int To) //返回第p小的节点 并移动到To的子节点中
    {if(!rt || p > T[rt].size) return 0;int x=rt;while(x){PushDown(x);if(p >= T[T[x].son[0]].size+1 && p <= T[T[x].son[0]].size+T[x].num)break;if(p > T[T[x].son[0]].size+T[x].num){p-=T[T[x].son[0]].size+T[x].num;x=T[x].son[1];}elsex=T[x].son[0];}Splay(x, 0);return x;}int Find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处
    {if(!rt) return 0;int x=rt;while(x){PushDown(x);if(T[x].key == key) break;x=T[x].son[key > T[x].key];}if(x) Splay(x, 0);return x;}int Prev() //返回根节点的前驱 非重点
    {if(!rt || !T[rt].son[0]) return 0;int x=T[rt].son[0];while(T[x].son[1]){PushDown(x);x=T[x].son[1];}Splay(x, 0);return x;}int next() //返回根结点的后继 非重点
    {if(!rt || !T[rt].son[1]) return 0;int x=T[rt].son[1];while(T[x].son[0]){PushDown(x);x=T[x].son[0];}Splay(x, 0);return x;}void Insert(int key,int K) //插入key值
    {if(!rt)rt=Newnode(key, 0, K);else{int x=rt, y=0;while(x){PushDown(x);y=x;if(T[x].key == key){T[x].num++;T[x].size++;break;}T[x].size++;//既然一定调整x=T[x].son[key > T[x].key];}if(!x)x = T[y].son[key > T[y].key] = Newnode(key, y, K);Splay(x, 0);}}void Delete(int key) //删除值为key的节点1个
    {int x=Find(key);if(!x) return;if(T[x].num>1){T[x].num--;PushUp(x);return;}int y=T[x].son[0];while(T[y].son[1])y=T[y].son[1];int z=T[x].son[1];while(T[z].son[0])z=T[z].son[0];if(!y && !z){rt=0;return;}if(!y){Splay(z, 0);T[z].son[0]=0;PushUp(z);return;}if(!z){Splay(y, 0);T[y].son[1]=0;PushUp(y);return;}Splay(y, 0);Splay(z, y);T[z].son[0]=0;PushUp(z);PushUp(y);}int GetRank(int key) //获得值<=key的节点个数 并将其转移到根处 若<key只需将<=换为<
    {if(!rt) return 0;int x=rt, ret=0, y=0;while(x){y=x;if(T[x].key <= key){ret += T[T[x].son[0]].size + T[x].num;x=T[x].son[1];}elsex=T[x].son[0];}Splay(y, 0);return ret;}//    这个删除太丑了
//    void Delete(int l, int r) //删除值在[l, r]中的所有节点 l!=r
//    {
//        if(!Find(l)) Insert(l);// 你这样写真的好吗? 泥煤
//        int p=Prev();
//        if(!Find(r)) Insert(r);
//        int q=next();
//        if(!p && !q)
//        {
//            rt=0;
//            return;
//        }
//        if(!p)
//        {
//            T[rt].son[0]=0;
//            PushUp(rt);
//            return;
//        }
//        if(!q)
//        {
//            Splay(p, 0);
//            T[rt].son[1]=0;
//            PushUp(rt);
//            return;
//        }
//        Splay(p, q);
//        T[p].son[1]=0;
//        PushUp(p);
//        PushUp(q);
//    }
}spt;int main() {int n,q;scanf("%d%d",&n,&q);spt.init();for(int i=1;i<=n;i++){int tmp;scanf("%d",&tmp);spt.Insert(i, tmp);}for(int i=0;i<q;i++){getchar();char sign;scanf("%c",&sign);long long ans=0;if(sign == 'Q'){int a,b;scanf("%d%d",&a,&b);if(a==b){int id = spt.Find(a);// markans = spt.T[id].K;//cout<<spt.T[id].K<<endl;
            }else{int ida,idb;idb = spt.Find(b);//在这题,因为点没有删除,所以点的标号和splaytree中标号一致。ida = spt.Find(a);//但是有lazy标记,所以还是得找一遍,可以把标记往下推。
                spt.Splay(idb, ida);int idson = spt.T[idb].son[0];//spt.PushDown(idb);ans = spt.T[idb].K + spt.T[ida].K + spt.T[idson].sumk;}printf("%I64d\n",ans);//cout<<ans<<endl;
        }else{int a,b,c;scanf("%d%d%d",&a,&b,&c);if(a==b){int id = spt.Find(a);spt.T[id].K += c;spt.T[id].sumk += c;// 这个节点的值改变了,还是得往上推spt.Splay(id, 0);}else{int ida,idb;idb = spt.Find(b);ida = spt.Find(a);spt.T[ida].K += c;//spt.T[ida].sumk += c;spt.T[idb].K += c;//spt.T[idb].sumk += c;
                spt.Splay(idb, ida);int idson = spt.T[idb].son[0];if(idson != 0){spt.T[ idson ].sumk += spt.T[ idson ].size*c;spt.T[ idson ].K += c;Add[idson] += c;// 当全局变量来用spt.Splay(idson, 0);//还得往上推一下吧
                }}
        }}return 0;
}

splay tree成段更新,成段查询poj3466相关推荐

  1. [HDOJ4027]Can you answer these queries?(线段树,特殊成段更新,成段查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027 RT,该题要求每次更新是更新所有节点,分别求平方根,查询是求和.昨晚思前想后找有没有一个数学上的 ...

  2. uscao 线段树成段更新操作及Lazy思想(POJ3468解题报告)

    线段树成段更新操作及Lazy思想(POJ3468解题报告) 标签: treequerybuildn2cstruct 2011-11-03 20:37 5756人阅读 评论(0) 收藏 举报  分类: ...

  3. NYOJ 1068 ST(线段树之 成段更新+区间求和)

    ST 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 "麻雀"lengdan用随机数生成了后台数据,但是笨笨的他被妹纸的问题给难住了... 已知len ...

  4. HDU 3974 Assign the task(dfs时间戳+线段树成段更新)

    题意:给定点的上下级关系,规定假设给i分配任务a.那么他的全部下属.都停下手上的工作,開始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: Sample Input 1 5 4 3 3 ...

  5. HDOJ 1698 Just a Hook(线段树成段更新)

    题意: 屠夫的钩子区间是1~n,每段可能由铜,银,金组成,价值分别为1,2,3,进行一系列的更新之后,求钩子的总价值. 思路: 线段树的成段更新:要设置一个临时的线段树,每次更新的时候把更新段的值放在 ...

  6. Hdu 1794 【二维成段更新】.cpp

    题意: 给出一个n*n的矩阵和m个数,从m个数中选几个数填入矩阵中值为0的空格中,使矩阵的和最大. 矩阵的和的定义是:所有子矩阵的数的和的和..   思路: 要想矩阵的和最大..应该使m个数中值大的数 ...

  7. cad连接不同线段的端点_【CAD图形】】为什么CAD连续的图形无法连接成完整的多段线...

    为什么 CAD 连续的图形无法连接成完整的多段线 在使用 CAD 软件绘图的时候, 有时候出于绘图需要, 设计师需要将连续的 CAD 图形连接成 完整的额多段线, 但是很多人总是无法成功操作, 这是怎 ...

  8. Oracle 单字段拆分成多行

    Oracle 单字段拆分成多行 性能上方法1最优,其次方法2,方法3因为有distinct,性能差 方法1: SELECT stuid,substr(a.stuname, instr(a.stunam ...

  9. (分配问题)你让工人为你工作7天,给工人的回报是一根金条。金条平分成相连的7段,你必须在每天结束时给他们一段金条

    问题描述 你让工人为你工作7天,给工人的回报是一根金条.金条平分成相连的7段,你必须在每天结束时给他们一段金条,如果只许你两次把金条弄断,你如何给你的工人付费? 解答思路 把金条分成(1,2).(3) ...

  10. NYOJ 1068 ST(段树 为段更新+间隔总和)

    ST 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描写叙述 "麻雀"lengdan用随机数生成了后台数据.可是笨笨的他被妹纸的问题给难住了. .. 已知 ...

最新文章

  1. 11月18日珠三角城市人口迁徙可视化(和弦图)
  2. Java多线程分析案例
  3. mysql去掉两个最高分_如何计算去掉一个最高分和一个最低分后的平均分?
  4. vmware提示:此虚拟机似乎正在使用中,无法取得所有权的解决办法
  5. 【LiveVideoStack线上分享】FFmpeg深度学习模块架构与代码实践
  6. Django MTV 开发模式 + 数据库配置
  7. os2计算机网络,计算机网络 第二章 物理层
  8. 详解Visual Studio 2010中ASP.NET新增23项功能 转
  9. OA协同办公软件评测 —— Tower篇
  10. 笔记本电脑连接加密无线路由器。
  11. DirectVobSub(VsFilter)的基本原理和实现实现
  12. fastadmin表格操作
  13. 代码托管平台的待办事项你知道吗 ?|GitCode
  14. ELK——ElasticStack日志分析平台
  15. overleaf 常见数学公式 latex
  16. Word调查问卷表格统计
  17. 32位计算机如何升级,32位改64位系统怎么安装 32位怎么升级64位系统
  18. ROS kinetic 运行s_msckf和 vins_fusion
  19. 输入年、月,判断该月有多少天
  20. html让视频跟图片之间无缝,图片、样式、音视频之间的无缝拼接,教你一个万能方法!...

热门文章

  1. Ubuntu-10.04中设置和修改root密码
  2. JQuery Dialog(转)
  3. Raspberry Pi 实现刷卡就亮灯
  4. JAVA之day3对象
  5. Excel 2007 底层实现方式
  6. python多重继承super父类参数_Python super()函数使用及多重继承
  7. flume学习(九):使用Morphline Interceptor
  8. 剖析Disruptor:为什么会这么快?(三)揭秘内存屏障
  9. SAP 生产订单变更管理 OCM Order Changement Management
  10. 如此逼真的高清图像居然是端到端网络生成的?GANs 自叹不如 | ICCV 2017