您的位置:首页 > 其它

[HihoCoder]#1078 : 线段树的区间修改

2017-06-01 23:28 399 查看
华电北风吹

日期:2017-06-01

题目链接:

http://hihocoder.com/problemset/problem/1078

题目分析:

不得不说模板代码采用了自顶向下的思路计算量就是小。模板代码思路,对于每个节点,如果整个区间值一致的话,更新和查找到此就直接返回了,不对子树进行更新,不过要保存个lazy属性,以后如果更新或者查询需要进入到区间树子节点的时候,可以凭lazy属性知道里面的值需要pushdown。

模板代码:

#include <iostream>
using namespace std;

const int maxn = 100100;

struct node
{
int left;
int right;
int lazy;
int sum;
};
node data[maxn << 2];

void build(int i, int left, int right)
{
data[i].left = left;
data[i].right = right;
data[i].lazy = 0;
if(left == right){
scanf("%d",&data[i].sum);
return;
}
int mid = (left + right) >> 1;
build(i << 1, left, mid);
build(i << 1 | 1, mid + 1, right);
data[i].sum = data[i << 1].sum + data[i << 1 | 1].sum;
}

void pushdown(int v)
{
if(data[v].lazy){
data[v << 1].sum = (data[v << 1].right - data[v << 1].left + 1) * data[v].lazy;
data[v << 1 | 1].sum = (data[v << 1 | 1].right - data[v << 1 | 1].left + 1) * data[v].lazy;
data[v << 1].lazy = data[v << 1 | 1].lazy = data[v].lazy;
data[v].lazy = 0;
}
}

void update(int v, int left, int right, int val){
if(data[v].left >= left && data[v].right <= right){
data[v].sum = (data[v].right - data[v].left + 1) * val;
data[v].lazy = val;
return;
}
pushdown(v);
if(left <= data[v << 1].right)
update(v << 1, left, right, val);
if(right >= data[v << 1 | 1].left)
update(v << 1 | 1, left, right, val);
data[v].sum = data[v << 1].sum + data[v << 1 | 1].sum;
}

int query(int v, int left,int right){
if(data[v].left >= left && data[v].right <= right)
return data[v].sum;
pushdown(v);
int a = 0, b = 0;
if(left <= data[v << 1].right)
a = query(v << 1, left, right);
if(right >= data[v << 1 | 1].left)
b = query(v << 1 | 1, left, right);
data[v].sum = data[v << 1].sum + data[v << 1 | 1].sum;
return a + b;
}

int main()
{
int n,q,op,a,b,val;
while(~scanf("%d",&n)){
build(1, 1, n);
scanf("%d",&q);
while(q--){
scanf("%d %d %d", &op, &a, &b);
if(op){
scanf("%d",&val);
update(1, a, b, val);
}else printf("%d\n",query(1, a, b));
}
}
return 0;
}


自己代码(超时):

#include <stdio.h>
#include <algorithm>
using namespace std;

#define INT_MAX 0x7fffffff

struct node
{
int leftID, rightID;
int sum;
};

node data[4000000 + 10];
int father[1000000 + 2];

void Build(int i, int left, int right)
{
int middle = (left + right) >> 1;
data[i].leftID = left;
data[i].rightID = right;
data[i].sum = 0;
if (left == right){
father[left] = i;
return;
}
Build(i << 1, left, middle);
Build(i << 1 | 1, middle + 1, right);
}

void Update(int id, int offset)
{
data[id].sum += offset;
if (id == 1){
return;
}
Update(id >> 1, offset);
}

int Query(int i, int l, int r)
{
int result = 0;
if (data[i].leftID == l&&data[i].rightID == r){
return data[i].sum;
}
int middle = (data[i].leftID + data[i].rightID) >> 1;
if (l <= middle){
if (r <= middle){
return Query(i << 1, l, r);
}else{
result += Query(i << 1, l, middle);
}
}
if (r >= middle + 1){
if (l >= middle + 1){
return Query(i << 1 | 1, l, r);
}else{
result += Query(i << 1 | 1, middle + 1, r);
}
}
return result;
}

int main()
{
int n, m;
int temp;
scanf("%d", &n);
Build(1, 1, n);

for (int i = 1; i <= n; i++){
scanf("%d", &temp);
Update(father[i], temp);
}

scanf("%d", &m);
int flag, left, right, val;
for (int i = 0; i<m; i++){
scanf("%d", &flag);
if (flag == 0){
scanf("%d%d", &left, &right);
int result = Query(1, left, right);
printf("%d\n", result);
}else{
scanf("%d%d%d", &left, &right, &val);
for(int j = left; j <= right; j++){
Update(father[j], val - data[father[j]].sum);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: