SPOJ 11840. Sum of Squares with Segment Tree (线段树,区间更新)
http://www.spoj.com/problems/SEGSQRSS/
SPOJ Problem Set (classical)11840. Sum of Squares with Segment TreeProblem 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:
2 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).
1 st nd x -- add "x" to all numbers with indices in [st, nd] (1
<= st <= nd <= N, and
-1,000 <= x <= 1,000).
0 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 (线段树,区间更新)的更多相关文章
- SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并
Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...
- BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】
A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...
- HDU 4107 Gangster Segment Tree线段树
这道题也有点新意,就是须要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提快速度的目的. 本题过的人非常少,由于大部分都超时了,我严格依照线段树的方法去写.一開始竟然也超时. 然后 ...
- Implementation:Segment Tree 线段树
早就听人提起过线段树,今天有题搞不出来,讨论上说要用一下线段树,看了下,本质上是空间划分索引,只不过是一维上面的,如果在二维则是四叉树,三维则是八叉树,如果可以动态调整那么跟R-Tree就很相似了,他 ...
- SPOJ GSS1_Can you answer these queries I(线段树区间合并)
SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- 【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)
[BZOJ3638]Cf172 k-Maximum Subsequence Sum Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交 ...
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
随机推荐
- WRTnode 的 HTTP Web 开关实验(2016-05-16)
前言 这里是节取自 物联网的任意门——WRTnode2R 评测 中的 http web 开关灯实验,所以有一些前置设置如果没有描述清楚可参考该处. 正文 步骤一:编辑一个 html 文件,放在 /ww ...
- struts jsp传值到action,乱码的解决方案
使用了Struts框架,前台写好了编码为utf-8 <%@ page language="java" contentType="text/html; charset ...
- linux 下dd命令直接清除分区表(不用再fdisk一个一个的删除啦)
分区表是硬盘的分区信息,要删除一个硬盘的所有分区表很麻烦的,需要fdisk一个一个的删除,其实dd命令可直接清除分区信息,当然,这也是linux给root用户留下的作死方法之一.dd 命令主要参数如下 ...
- JS sort()实用技巧
[1, 3, 9, 2].sort(); // Returns: [1, 2, 3, 9] // 返回 [1, 2, 3, 9] --这没错,但它还有更强大的用法,比如这样: var data=[ ...
- Qt中将QTableView中的数据导出为Excel文件
如果你在做一个报表类的程序,可能将内容导出为Excel文件是一项必须的功能.之前使用MFC的时候我就写过一个类,用于将grid中的数据导出为Excel文件.在使用了QtSql模块后,我很容易的将这个类 ...
- BZOJ 1708: [Usaco2007 Oct]Money奶牛的硬币
1708: [Usaco2007 Oct]Money奶牛的硬币 Description 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统 ...
- JavaScript+XML+VBA导出报表初步构想
最近在做人事档案管理系统遇到的一个问题就是种类多.数量大的报表打印问题.这个系统的一个特点就是信函打印,各种介绍信.各种证明信.对于这样的重复性的功能,最好的方法就是所有的报表实现格式套用. 经过分析 ...
- CentOS下mysql最大连接数设置 1040 too many connection
当最大连接数比較小时,可能会出现"1040 too many connection"错误. 能够通过改动配置文件来改动最大连接数,但我连配置文件在哪都不知道,应该怎么办呢? 首先须 ...
- VS2005+WINDDK+Driver Studio 3.2个人总结
通过在网上搜索大量的资料,终于把环境搭建起来.对于我这样的驱动新手来说,理应把高手们的东西整理并总结下,方便以后的初学者. 这三个软件的安装顺序没有具体规定,也有高手推荐的顺序,我自己也是重复安装卸载 ...
- ThinkPHP的验证码刷新显示和验证码显示不出来的原因
1.应当这样<imp src='验证码路径' onclick="this.src='验证码路径?'+Math.random()">;如果后面不加Math.random( ...