poj3468 splay(成段跟新 区间求和)
用splay做了一遍。
建树时是按照数列序号从小到大排好的,每个节点左子树的序号小于右子树的序号及这个节点本身。
由于查询[l,r]要伸展l-1,r+1所以我们要多加2个结点,保证边界处理时不出问题。由于这样每次查找l-1时,
要找的应该是l(r+1也是找r+2)。
- #include <iostream>
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- #define ll __int64
- #define key_value ch[ch[root][1]][0]
- using namespace std;
- const int MAXN=;
- int pre[MAXN],ch[MAXN][],key[MAXN],tot1,root;
- int siz[MAXN],tot2,a[MAXN],n,s[MAXN];
- ll lazy[MAXN],sum[MAXN];
- void Treavel(int x)
- {
- if(x)
- {
- Treavel(ch[x][]);
- printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d add=%2d sum=%I64d\n",x,ch[x][],ch[x][],pre[x],siz[x],key[x],lazy[x],sum[x]);
- Treavel(ch[x][]);
- }
- }
- void debug()
- {
- printf("root:%d\n",root);
- Treavel(root);
- }
- void Newnode(int &rt,int father,int k)
- {
- if(tot2)
- rt = s[--tot2];
- else
- rt = ++tot1;
- pre[rt] = father;
- key[rt] = k;
- siz[rt] = ;
- lazy[rt] = ;
- ch[rt][] = ch[rt][] = ;
- }
- void pushup(int rt)
- {
- siz[rt] = siz[ch[rt][]] + siz[ch[rt][]] + ;
- sum[rt] = sum[ch[rt][]] + sum[ch[rt][]] + key[rt];
- }
- void pushdown(int rt)
- {
- if(lazy[rt]){
- lazy[ch[rt][]] += lazy[rt];
- lazy[ch[rt][]] += lazy[rt];
- key[ch[rt][]] += lazy[rt];
- key[ch[rt][]] += lazy[rt];
- sum[ch[rt][]] += (ll)siz[ch[rt][]]*lazy[rt];
- sum[ch[rt][]] += (ll)siz[ch[rt][]]*lazy[rt];
- lazy[rt] = ;
- }
- }
- void build(int &rt,int l,int r,int father)
- {
- if(l > r)
- return ;
- int m = (l+r)/;
- Newnode(rt,father,a[m]);
- build(ch[rt][],l,m-,rt);
- build(ch[rt][],m+,r,rt);
- pushup(rt);
- }
- void Init()
- {
- int i,j;
- for(i=; i<=n; i++){
- scanf("%d",&a[i]);
- }
- root = tot1 = tot2 = ;
- ch[root][] = ch[root][] = key[root] = siz[root] = lazy[root] = pre[root] = sum[root] = ;
- Newnode(root,,-);
- Newnode(ch[root][],root,-);//头尾各加入一个点
- build(key_value,,n,ch[root][]);//让所有数据夹在这两个点之间 由于树的结构 所以在ch[ch[root][1]][0]
- pushup(ch[root][]);
- pushup(root);
- }
- void Rotate(int rt,int kind)
- {
- int y = pre[rt];
- pushdown(y);
- pushdown(rt);
- ch[y][!kind] = ch[rt][kind];
- pre[ch[rt][kind]] = y;
- if(pre[y]){
- ch[pre[y]][ch[pre[y]][]==y] = rt;
- }
- pre[rt] = pre[y];
- ch[rt][kind] = y;
- pre[y] = rt;
- pushup(y);
- }
- void splay(int rt,int goal)
- {
- pushdown(rt);
- while(pre[rt] != goal)
- {
- if(pre[pre[rt]] == goal){
- Rotate(rt,ch[pre[rt]][]==rt);
- }
- else {
- int y = pre[rt];
- int kind = ch[pre[y]][]==y;
- if(ch[y][kind] == rt){
- Rotate(rt,!kind);
- Rotate(rt,kind);
- }
- else {
- Rotate(y,kind);
- Rotate(rt,kind);
- }
- }
- }
- pushup(rt);
- if(goal == )
- root = rt;
- }
- int Get_kth(int rt,int k)
- {
- pushdown(rt);
- int t = siz[ch[rt][]] + ;
- if(t == k){
- return rt;
- }
- else if(t > k){
- return Get_kth(ch[rt][],k);
- }
- else
- return Get_kth(ch[rt][],k-t);
- }
- void updata(int l,int r,int v)
- {
- splay(Get_kth(root,l),);
- splay(Get_kth(root,r+),root);
- key[key_value] += v;
- lazy[key_value] += v;
- sum[key_value] += (ll)v*siz[key_value];
- }
- ll query(int l,int r)
- {
- splay(Get_kth(root,l),);//由于开始的时候多添加了2个结点,所以编号都是在这2个结点之间的 所以查询的时候都要大1
- splay(Get_kth(root,r+),root);
- return sum[key_value];
- }
- int main()
- {
- int i,j,q;
- while(~scanf("%d%d",&n,&q))
- {
- Init();
- //debug();
- char s[];
- while(q--)
- {
- scanf("%s",s);
- if(s[] == 'C'){
- int x,y,z;
- scanf("%d%d%d",&x,&y,&z);
- updata(x,y,z);
- }
- else {
- int x,y;
- scanf("%d%d",&x,&y);
- printf("%I64d\n",query(x,y));
- }
- }
- }
- }
poj3468 splay(成段跟新 区间求和)的更多相关文章
- UESTC-1057 秋实大哥与花(线段树+成段加减+区间求和)
秋实大哥与花 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit St ...
- 线段树(成段更新,区间求和lazy操作 )
hdu1556 Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- POJ-3468 A Simple Problem with Integers (区间求和,成段加减)
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of op ...
- POJ 3468.A Simple Problem with Integers-线段树(成段增减、区间查询求和)
POJ 3468.A Simple Problem with Integers 这个题就是成段的增减以及区间查询求和操作. 代码: #include<iostream> #include& ...
- poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)
题目链接 题意: 只有这两种操作 C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.&quo ...
- POJ 3225.Help with Intervals-线段树(成段替换、区间异或、简单hash)
POJ3225.Help with Intervals 这个题就是对区间的各种操作,感觉这道题写的一点意思都没有,写到后面都不想写了,而且更神奇的是,自己的编译器连结果都输不出来,但是交上就过了,也是 ...
- poj_3468线段树成段更新求区间和
#include<iostream> #include<string.h> #include<cstdio> long long num[100010]; usin ...
- 线段树---poj3468 A Simple Problem with Integers:成段增减:区间求和
poj3468 A Simple Problem with Integers 题意:O(-1) 思路:O(-1) 线段树功能:update:成段增减 query:区间求和 Sample Input 1 ...
- poj3468 A Simple Problem with Integers(线段树模板 功能:区间增减,区间求和)
转载请注明出处:http://blog.csdn.net/u012860063 Description You have N integers, A1, A2, ... , AN. You need ...
随机推荐
- Java向上转型与向下转型
一.向上转型 例如:Parent p=new Son(); 这样引用p只能调用子类中重载父类的方法:但属性是父类的:如果想调用子类属性的话,可以用getter()方法. 二.向下转型 子类对象的父类引 ...
- 边工作边刷题:70天一遍leetcode: day 81
Encode and Decode Strings 要点:题的特点:不是压缩,而是encode为字节流.所以需要找delimiter来分割每个word,但是delimiter可能是字符本身,所以可以用 ...
- python刷题专用函数。。
无它,非bin()莫属. bin(x) Convert an integer number to a binary string. The result is a valid Python expre ...
- java7-4 继承的练习
1.Override和Overload的区别,Overload能改变返回值类型吗? 答: Override就是方法重写:在子类中,出现和父类中一模一样的方法声明的现象 Overload就是方法重载:在 ...
- 注解与反射 ---Spring与Mybatis等框架的实现原理
Java中各大框架,无论是AOP 还是 IoC 其基本实现思路都是源自Java 运行时支撑的反射功能, 而反射最基本的一点就是 任何一个类 其在JVM环境中,都有一个对象的Class对象,这个对象提供 ...
- 两种方式判断类的存在→className getAttribute
通过className获取 var p = document.getElementsByTagName('p'); for(var i = 0;i <p.length;i++){ if(p[i] ...
- AFN框架基本使用
0.AFN框架基本使用 0.1 AFN内部结构 AFN结构体 - NSURLConnection + AFURLConnectionOperation(已经被废弃) + AFHTTPRequestOp ...
- [转]iOS 应用内付费(IAP)开发步骤
FROM : http://blog.csdn.net/xiaoxiangzhu660810/article/details/17434907 参考文章链接: (1)http://mobile.51c ...
- string与stringBuilder的效率与内存占用实测
using UnityEngine; using System.Diagnostics; using System.Text; using UnityEngine.UI; public class s ...
- php基础31:正则匹配-元字符
<?php //2.正则表达式:元字符 $model = "/php/"; $string = "php"; // 1.元字符 [a-z] 匹配任何a-z ...