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 && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)

    题意 : 给出一段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. WRTnode 的 HTTP Web 开关实验(2016-05-16)

    前言 这里是节取自 物联网的任意门——WRTnode2R 评测 中的 http web 开关灯实验,所以有一些前置设置如果没有描述清楚可参考该处. 正文 步骤一:编辑一个 html 文件,放在 /ww ...

  2. struts jsp传值到action,乱码的解决方案

    使用了Struts框架,前台写好了编码为utf-8 <%@ page language="java" contentType="text/html; charset ...

  3. linux 下dd命令直接清除分区表(不用再fdisk一个一个的删除啦)

    分区表是硬盘的分区信息,要删除一个硬盘的所有分区表很麻烦的,需要fdisk一个一个的删除,其实dd命令可直接清除分区信息,当然,这也是linux给root用户留下的作死方法之一.dd 命令主要参数如下 ...

  4. JS sort()实用技巧

    [1, 3, 9, 2].sort(); // Returns: [1, 2, 3, 9] // 返回 [1, 2, 3, 9]   --这没错,但它还有更强大的用法,比如这样: var data=[ ...

  5. Qt中将QTableView中的数据导出为Excel文件

    如果你在做一个报表类的程序,可能将内容导出为Excel文件是一项必须的功能.之前使用MFC的时候我就写过一个类,用于将grid中的数据导出为Excel文件.在使用了QtSql模块后,我很容易的将这个类 ...

  6. BZOJ 1708: [Usaco2007 Oct]Money奶牛的硬币

    1708: [Usaco2007 Oct]Money奶牛的硬币 Description 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统 ...

  7. JavaScript+XML+VBA导出报表初步构想

    最近在做人事档案管理系统遇到的一个问题就是种类多.数量大的报表打印问题.这个系统的一个特点就是信函打印,各种介绍信.各种证明信.对于这样的重复性的功能,最好的方法就是所有的报表实现格式套用. 经过分析 ...

  8. CentOS下mysql最大连接数设置 1040 too many connection

    当最大连接数比較小时,可能会出现"1040 too many connection"错误. 能够通过改动配置文件来改动最大连接数,但我连配置文件在哪都不知道,应该怎么办呢? 首先须 ...

  9. VS2005+WINDDK+Driver Studio 3.2个人总结

    通过在网上搜索大量的资料,终于把环境搭建起来.对于我这样的驱动新手来说,理应把高手们的东西整理并总结下,方便以后的初学者. 这三个软件的安装顺序没有具体规定,也有高手推荐的顺序,我自己也是重复安装卸载 ...

  10. ThinkPHP的验证码刷新显示和验证码显示不出来的原因

    1.应当这样<imp src='验证码路径' onclick="this.src='验证码路径?'+Math.random()">;如果后面不加Math.random( ...