http://www.spoj.com/problems/SEGSQRSS/

SPOJ Problem Set (classical)

11840. Sum of Squares with Segment Tree

Problem code: SEGSQRSS

Segment trees are extremely useful.  In particular "Lazy Propagation" (i.e. see
here, for example
) allows one to compute sums over a range in O(lg(n)), and update ranges in O(lg(n)) as well.  In this problem you will compute something much harder:

The sum of squares over a range with range updates of 2 types:

1) increment in a range

2) set all numbers the same in a range.

Input

There will be T (T <= 25) test
cases in the input file.  First line of the input contains two positive integers, N (N <= 100,000) and Q
(Q <= 100,000)
. The next line contains N integers,
each at most 1000.  Each of the next Qlines
starts with a number, which indicates the type of operation:

st nd  -- return the sum of the squares of the numbers with
indices in [st, nd]
{i.e., from st to nd inclusive} (1
<= st <= nd <= N).

st nd x -- add "x" to all numbers with indices in [st, nd] (1
<= st <= nd <= N, and
-1,000 <= x <= 1,000).

st nd x -- set all numbers with indices in
[st, nd] to
"x" (1 <= st <= nd <= N, and
-1,000 <= x <= 1,000).

Output

For each test case output the “Case <caseno>:” in
the first line and from the second line output the sum of squares for each operation of type 2.  Intermediate overflow will not occur
with proper use of 64-bit signed integer.

Example

Input:

2

4 5

1 2 3 4

2 1 4

0 3 4 1

2 1 4

1 3 4 1

2 1 4

1 1

1

2 1 1

Output:

Case 1:

30

7

13

Case 2:

1

 

Added by: Chen Xiaohong
Date: 2012-07-11
Time limit: 6s
Source limit: 50000B
Memory limit: 256MB
Cluster: Pyramid (Intel Pentium III 733 MHz)
Languages: All


题意:

有三种操作:将区间中的全部数置为x;将区间中的全部数加上x;求区间内全部数的平方和。

分析:

先考虑假设不须要求平方和,仅仅是求和,我们须要维护这些数据:addv-区间内的数共同加上的值;setv-区间内的数都置为的值(setv=INF表示不设置);sumv-区间内的数加上addv之前的值。

但这题求的是平方和。似乎不是非常好维护。假设仅仅是set操作,还是非常好维护的,那么难点就在于add操作了。考虑例如以下等式:(x+v)^2=x^2+2xv+v^2,x是add操作之前的数,v是add的数。这是一个数的情况。那么一段区间内的数呢?

显然有sum(xi^2)+(v^2)*length+2*sum(xi)*v。这样问题就迎刃而解了,仅仅要再维护一个区间的平方和即可,当set时直接改,add时加上(v^2)*length+2*sum(xi)*v即可。

/*
*
* Author : fcbruce
*
* Time : Fri 03 Oct 2014 04:16:10 PM CST
*
*/
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10 #ifdef _WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif #define maxm
#define maxn 100007 using namespace std; int addv[maxn<<2],setv[maxn<<2];
long long sumv[maxn<<2],sqrsumv[maxn<<2]; inline void pushdown(int k,int l,int r)
{
int lc=k*2+1,rc=k*2+2,m=l+r>>1;
addv[lc]+=addv[k];
addv[rc]+=addv[k];
addv[k]=0; if (setv[k]!=INF)
{
setv[lc]=setv[rc]=setv[k];
sumv[lc]=(LL)setv[lc]*(m-l);sumv[rc]=(LL)setv[rc]*(r-m);
sqrsumv[lc]=sqr((LL)setv[k]*(m-l));sqrsumv[rc]=sqr((LL)setv[rc])*(r-m);
addv[lc]=addv[rc]=0;
setv[k]=INF;
}
} inline void pushup(int k,int l,int r)
{
int lc=k*2+1,rc=k*2+2,m=l+r>>1; sumv[k]=sumv[lc]+sumv[rc]+(LL)addv[lc]*(m-l)+(LL)addv[rc]*(r-m);
sqrsumv[k]=sqrsumv[lc]+sqrsumv[rc]+(LL)(r-l)*(addv[k])+2ll*sumv[k]*addv[k];
} void build(int k,int l,int r)
{
addv[k]=0;
setv[k]=INF;
sumv[k]=sqrsumv[k]=0ll; if (r-l==1)
{
scanf("%d",&sumv[k]);
sqrsumv[k]=sqr((LL)sumv[k]);
return ;
} build(k*2+1,l,l+r>>1);
build(k*2+2,l+r>>1,r); pushup(k,l,r);
} void update_add(int a,int b,int v,int k,int l,int r)
{
if (b<=l || r<=a) return ;
if (a<=l && r<=b)
{
addv[k]+=v;
sqrsumv[k]+=sqr((LL)v)*(r-l)+2ll*v*sumv[k];
return ;
} pushdown(k,l,r); update_add(a,b,v,k*2+1,l,l+r>>1);
update_add(a,b,v,k*2+2,l+r>>1,r); pushup(k,l,r);
} void update_set(int a,int b,int v,int k,int l,int r)
{
if (b<=l || r<=a) return ;
if (a<=l && r<=b)
{
addv[k]=0;
setv[k]=v;
sumv[k]=(LL)v*(r-l);
sqrsumv[k]=sqr((LL)v)*(r-l);
return ;
} pushdown(k,l,r); update_set(a,b,v,k*2+1,l,l+r>>1);
update_set(a,b,v,k*2+2,l+r>>1,r); pushup(k,l,r);
} long long query(int a,int b,int k,int l,int r)
{
if (b<=l || r<=a) return 0ll;
if (a<=l && r<=b) return sqrsumv[k]; pushdown(k,l,r); return query(a,b,k*2+1,l,l+r>>1)+query(a,b,k*2+2,l+r>>1,r);
} int main()
{
#ifdef FCBRUCE
freopen("/home/fcbruce/code/t","r",stdin);
#endif // FCBRUCE int T_T,__=0;
scanf("%d",&T_T); while (T_T--)
{
int n,m;
scanf("%d%d",&n,&m); build(0,0,n); printf("Case %d:\n",++__); int op,a,b,v;
while (m--)
{
scanf("%d",&op); switch (op)
{
case 0:
scanf("%d%d%d",&a,&b,&v);
a--;
update_set(a,b,v,0,0,n);
break;
case 1:
scanf("%d%d%d",&a,&b,&v);
a--;
update_add(a,b,v,0,0,n);
break;
case 2:
scanf("%d %d",&a,&b);
a--;
printf(lld "\n",query(a,b,0,0,n));
break;
}
}
} return 0;
}

SPOJ 11840. Sum of Squares with Segment Tree (线段树,区间更新)的更多相关文章

  1. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  2. SPOJ D-query &amp;&amp; HDU 3333 Turing Tree (线段树 &amp;&amp; 区间不相同数个数or和 &amp;&amp; 离线处理)

    题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...

  3. BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】

    A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...

  4. HDU 4107 Gangster Segment Tree线段树

    这道题也有点新意,就是须要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提快速度的目的. 本题过的人非常少,由于大部分都超时了,我严格依照线段树的方法去写.一開始竟然也超时. 然后 ...

  5. Implementation:Segment Tree 线段树

    早就听人提起过线段树,今天有题搞不出来,讨论上说要用一下线段树,看了下,本质上是空间划分索引,只不过是一维上面的,如果在二维则是四叉树,三维则是八叉树,如果可以动态调整那么跟R-Tree就很相似了,他 ...

  6. SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...

  7. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  8. 【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)

    [BZOJ3638]Cf172 k-Maximum Subsequence Sum Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交 ...

  9. 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

随机推荐

  1. 安卓 JDK、SDK、ADT 区别

    问题一:android软件开发是用java语法,但是为什么开发环境还需要jdk,有android sdk不就可以了吗? 答: 我知道写字要用笔,但为什么还需要笔芯(墨水),有笔杆不就可以了吗? 问题二 ...

  2. js020-JSON

    js020-JSON 20.1 语法 JSON的语法可以表示为一下三种类型的值. 简单值 使用与JS相同的语法,可以在JSON中表示字符串.数值.布尔值和null,但是JSON不支持JS中的特殊性Un ...

  3. strtok和strtok_r

    1.strtok()函数的用法 函数原型:char *strtok(char *s, const char *delim); Function:分解字符串为一组字符串.s为要分解的字符串,delim为 ...

  4. 高级私人定制西服品牌:XUAN PRIVE 为定制而生_乐活_onlylady女人志

    高级私人定制西服品牌:XUAN PRIVE 为定制而生_乐活_onlylady女人志 高级私人定制西服品牌:XUAN PRIVE 为定制而生

  5. LinkedList的分析(转)

    一.源码解析 1. LinkedList类定义. public class LinkedList<E> extends AbstractSequentialList<E> im ...

  6. 把Excel工作簿的每个工作表提取出来保存为新工作簿

    平台:MS office 2010 任务:有个excel工作簿,其中有上百个工作表,要求把每一个工作表全部保存为新工作簿,如果一个一个复制出来太傻了,可以用excel自带的VB解决. 方法:打开工作簿 ...

  7. 第二章:在HTML中使用JavaScript

    1:在使用<script>嵌入JavaScript代码死,记住不要在代码中的任何地方出现"</script>"字符串 例如,浏览器在加载下面所示代码时就会产 ...

  8. Django中下划线的用法介绍(一)

    在Django中有相当多的操作是通过双下划线与动作连接起来使用,为了以后更加方便的查找和使用,现在总结以下Django中基本的双下划线操作 比较符:大于--gt  小于--lt 等于--eq  大于等 ...

  9. JAVA_SE基础——62.String类的构造方法

    下面我先列出初学者目前用到的构造方法 String 的构造方法:     String()  创建一个空内容 的字符串对象.   String(byte[] bytes)  使用一个字节数组构建一个字 ...

  10. day14.生成器进阶,推导式

    生成器中取值的三种方法 方法1:next() 方法2:for 循环 方法3:数据类型的强制转换 def func(): for i in range(20): yield '赛车*{}'.format ...