poj 3468 整理一下线段树的写法

// 对于延迟更新,我们在updata 和query的时候 pushdown和pushup两个东西都要存在 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
struct node
{
    ll l,r,sum,add;
} tree[10000*4];
ll a[100001];
//ll x,y;
void pushup(int id)
{
    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}
void build(ll l,ll r,int id)
{
    if(l==r)
    {
        tree[id].sum=a[l];
        return;
    }
    tree[id].l=l;
    tree[id].r=r;
    tree[id].add=0;
    ll mid=(l+r)/2;
    build(l,mid,id*2);
    build(mid+1,r,id*2+1);
    pushup(id);
}
void pushdown(int id)
{
    if(tree[id].add)
    {
        tree[id*2].add +=tree[id].add;
        tree[id*2+1].add += tree[id].add;

        tree[id*2].sum += (tree[id*2].r-tree[id*2].l+1)*(tree[id*2].add);
        tree[id*2+1].sum += (tree[id*2+1].r-tree[id*2+1].l+1)*(tree[id*2+1].add);
        tree[id].add=0;
    }
}

void updata(ll x,ll y,ll l,ll r,int id,ll k)
{
    if(x<=l && r<=y)// 在区间里面 就可以做一定操作
    {
        tree[id].sum += (r-l+1)*k;
        tree[id].add += k;
        return;
    }
    pushdown(id);//
    ll mid=(l+r)/2;
    if(x <= mid) updata(x,y,l,mid,id*2,k);
    if(y > mid)  updata(x,y,mid+1,r,id*2+1,k);
    pushup(id);
}

ll query(ll x,ll y,ll l,ll r,int id)
{
    if(x<=l && r<=y)
    {
        return tree[id].sum;
    }
    pushdown(id);
    ll mid=(l+r)/2;
    ll sum=0;
    if(x<=mid) sum+=query(x,y,l,mid,id*2);
    if(y>mid)  sum+=query(x,y,mid+1,r,id*2+1);
    pushup(id);//
    return sum;
}
int main()
{
    int n,q;
    ll x,y,k;
    while(scanf("%d %d",&n,&q)!=EOF)
    {
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
        }
        build(1,n,1);
        while(q--)
        {
            char s[3];
            scanf("%s",s);
            if(s[0]==‘Q‘)
            {
                scanf("%lld %lld",&x,&y);
                printf("%lld\n",query(x,y,1,n,1));
            }
            else if(s[0]==‘C‘)
            {
                scanf("%lld %lld %lld",&x,&y,&k);
                updata(x,y,1,n,1,k);
            }
        }
    }

    return 0;
}
时间: 2024-10-15 14:28:33

poj 3468 整理一下线段树的写法的相关文章

【整理】线段树30题

1,poj 1151 Atlantis: 求矩形面积并. 2,poj 1177 Picture: 求矩形轮廓的周长. 3,poj 1389 Area of Simple Polygons :同第一题. 4,poj 1823 Hotel :线段树线段的插入删除求线段树中最长的线段长度 5,poj 2104 K-th Number:线段树维护归并排序树+三次二分查找   (区间第k大 ,主席树也行,前者可以练习试一下). 6,poj 2155 Matrix :求二维平面的矩形信息,二维线段树,或者二

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

POJ训练计划2828_Buy Tickets(线段树/单点更新)

解题报告 题意: 插队完的顺序. 思路: 倒着处理数据,第i个人占据第j=pos[i]+1个的空位. 线段树维护区间空位信息. #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct node { int x,v; } num[201000]; int sum[1000000],ans[201000]; void cbtree(int rt,int l,in

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

HDU 1540 &amp;&amp; POJ 2892 Tunnel Warfare (线段树,区间合并).

~~~~ 第一次遇到线段树合并的题,又被律爷教做人.TAT. ~~~~ 线段树的题意都很好理解吧.. 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1540 http://poj.org/problem?id=2892 ~~~~ 我的代码:200ms #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #defin

POJ 2155 二维线段树

POJ 2155  二维线段树 思路:二维线段树就是每个节点套一棵线段树的树. 刚开始因为题目是求A[I,J],然后在y查询那直接ans^=Map[i][j]的时候没看懂,后面自己把图画出来了才理解. 因为只有0和1,所以可以用异或来搞,而不需要每次都需要修改. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #incl

POJ 2828 Buy Tickets (线段树)

题目大意: 排队有人插队,每一次都插到第 i 个人的后面. 最后输出顺序. 思路分析: 你会发现,如果反向处理的话,你就知道这个人是第几个了. 那么问题一下子就简化了. 就是在线段树上找第几个空位置就行了. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define lson num<<1

POJ 2155 二维线段树 经典的记录所有修改再统一遍历 单点查询

本来是想找一个二维线段树涉及懒惰标记的,一看这个题,区间修改,单点查询,以为是懒惰标记,敲到一半发现这二维线段树就不适合懒惰标记,你更新了某段的某列,但其实其他段的相应列也要打标记,但因为区间不一样,又不好打...也可能是我这是在套用一维线段树的思想,还有更好的二维线段树懒惰标记方法 反正到现在我还没搞定二维线段树的懒惰标记,因为这道题不用懒惰标记,因为是二进制序列,区间修改仅限于翻转操作,那就只要记录每次操作,最后查询的时候从上往下把所有修改都来上一遍,就可以了.就类似于树状数组的第二种用法,