/* THE PROGRAM IS MADE BY PYY */
/*----------------------------------------------------------------------------//
Copyright (c) 2012 panyanyany All rights reserved.
URL : http://poj.org/problem?id=3468
Name : 3468 A Simple Problem with Integers
Date : Sunday, April 15, 2012
Time Stage : 2 hours
Result:
10074419 panyanyany
3468
Accepted 12492K 2047MS C++
3148B 2012-04-15 12:46:56
Test Data :
Review :
普通的线段树方法要超时的,貌似还可以用splay tree(伸展树)。小媛的博客上说要用lazy方法……
//----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std ;
#define MEM(a, v) memset (a, v, sizeof (a)) // a for address, v for value
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define INF (0x3f3f3f3f)
#define MAXN 100010
#define LESN 10002
#define L(x) ((x)<<1)
#define R(x) (((x)<<1)|1)
#define DB /##/
typedef __int64 LL;
struct NODE {
int lf, rh;
LL sm, inc;
};
int q, n;
NODE segTree[MAXN*6]; //开小了一直runtime error
LL inc;
void build(int id, int lf, int rh)
{
segTree[id].lf = lf;
segTree[id].rh = rh;
segTree[id].sm = 0;
segTree[id].inc = 0;
if (lf == rh)
return ;
int mid = (lf + rh) / 2;
build(id<<1, lf, mid);
build((id<<1)|1, mid+1, rh);
}
LL update(int id, int lf, int rh, int val)
{
// 不在当前区间(一般来说都不用判断这个……)
if (segTree[id].lf > rh || segTree[id].rh < lf)
return 0;
// 到达匹配区间,这里不深入更新每一个叶子,因为会超时
if (segTree[id].lf == lf && segTree[id].rh == rh)
{
segTree[id].inc += val;
segTree[id].sm += val*(rh-lf+1);
return val*(rh-lf+1);
}
int mid = (segTree[id].lf + segTree[id].rh) / 2;
LL sum;
if (rh <= mid)
sum = update(id<<1, lf, rh, val);
else if (mid < lf)
sum = update((id<<1)|1, lf, rh, val);
else
sum = update(id<<1, lf, mid, val) + update((id<<1)|1, mid+1, rh, val);
segTree[id].sm += sum;
return sum;
}
LL query(int id, int lf, int rh)
{
if (rh < segTree[id].lf || segTree[id].rh < lf)
{
return 0;
}
if (inc = segTree[id].inc)
{ //查询的时候才更新子节点的增量
segTree[L(id)].inc += inc; //相当于对子区间进行一次update
segTree[L(id)].sm += inc * (segTree[L(id)].rh - segTree[L(id)].lf + 1);
segTree[R(id)].inc += inc;
segTree[R(id)].sm += inc * (segTree[R(id)].rh - segTree[R(id)].lf + 1);
segTree[id].inc = 0; //增量都传递到子区间去了,这里就要置零
}
if (lf == segTree[id].lf && rh == segTree[id].rh)
return segTree[id].sm;
int mid = (segTree[id].lf + segTree[id].rh) / 2;
if (rh <= mid)
return query(id<<1, lf, rh);
else if (mid < lf)
return query((id<<1)|1, lf, rh);
return query(id<<1, lf, mid) + query((id<<1)|1, mid+1, rh);
}
int main()
{
int i, j, x, y, v;
LL res;
char c;
while (scanf("%d%d", &n, &q) != EOF)
{
build(1, 1, n);
for (i = 1; i <= n; ++i)
{
scanf("%d", &j);
update(1, i, i, j);
}
while (q--)
{
getchar();
scanf("%c", &c);
scanf("%d %d", &x, &y);
if ('Q' == c)
{
res = query(1, x, y);
printf ("%I64d\n", res);
}
else
{
scanf("%d", &v);
update(1, x, y, v);
}
}
}
return 0;
}
分享到:
相关推荐
北大POJ1321-Chess Problem POJ1321-Chess Problem
NULL 博文链接:https://128kj.iteye.com/blog/1739064
NULL 博文链接:https://128kj.iteye.com/blog/1740501
POJ3468,线段树处理,注意longlongint
树状数组解决区间操作_高效 对数组的某个区间进行两种操作:1)求和 2)每个数据加常数。要求:时间复杂度低
POJ2528-Mayor's posters 【区间映射压缩(离散化)+线段树】 解题报告+AC代码 http://hi.csdn.net/!s/83XZJU ========> 我的所有POJ解题报告链接: http://blog.csdn.net/lyy289065406/article/details/6642573
北大POJ经典结题报告 北大POJ经典结题报告 北大POJ经典结题报告 注重方法,内容详尽,物超所值
很多的POJ题目答案!1000~1008,1011~1014,1016,1017,1019,1028,1032,1045,1046,1047,1050,1061,1067,1068,1088,1102,1159,1163,1183,1207,1218,1226,1247,1256,1258,1298,1316,1323,...
这是一道很不错的题目,即可以用线段树做也可以用树状数组,可谓经典。不过当然了线段树是比较难搞,而树状数组是极其简洁的,构造很简单,下面就分别来介绍一下两种方法...
poj2823,使用线段树进行查询区域间最大最小值,线段树初步
问题:求平面上多个矩形的总面积。 算法:线段树(经典的线段树题目)
如果你为在poj上找不到解题思路而痛苦,那么这本书可以为你带来惊喜,里面包括了poj上一部分题解题报告~
ACM POJ 解题报告北大POJ 大量解题代码
NULL 博文链接:https://128kj.iteye.com/blog/1739733
北大poj解题报告,希望能帮到软件工程的同学,每天一道,持之以恒,熟能生巧,与您共勉!
北大POJ1159-Palindrome
北大POJ1837-Balance
北大poj JAVA源码
北大POJ2996-Help Me with the Game 解题报告+AC代码
北大POJ第1005题答案(C语言)