线段树标版

  1 //s d s
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cstdlib>
  5 using namespace std;
  6 const int N=5000006;
  7 long long  a[N],sum[N];int miku[N];
  8 long long  b,c,d,e;
  9
 10 void update(int rt)
 11 {
 12     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 13 }
 14
 15 void build(int l,int r,int rt)
 16 {
 17     if(l==r)
 18     {
 19         sum[rt]=a[l];
 20         return ;
 21     }
 22     int m=(l+r)>>1;
 23     build(l,m,rt<<1);
 24     build(m+1,r,rt<<1|1);
 25     update(rt);
 26 }
 27 void pushdown(int l,int r,int m,int rt)
 28 {
 29     sum[rt<<1]+=miku[rt]*(m-l+1);
 30     sum[rt<<1|1]+=miku[rt]*(r-m);
 31     miku[rt<<1]+=miku[rt];
 32     miku[rt<<1|1]+=miku[rt];
 33     miku[rt]=0;
 34
 35  }
 36 void midify_interval(int l,int r,int rt,int nowl,int nowr,int neww)
 37 {
 38     if(nowl==l&&nowr==r)
 39     {
 40         miku[rt]+=neww;
 41         sum[rt]+=neww*(r-l+1);
 42         return ;
 43     }
 44     int m=(l+r)>>1;
 45     pushdown(l,r,m,rt);
 46     if(nowr<=m) midify_interval(l,m,rt<<1,nowl,nowr,neww);
 47     else if(nowl>m) midify_interval(m+1,r,rt<<1|1,nowl,nowr,neww);
 48     else
 49     {
 50         midify_interval(l,m,rt<<1,nowl,m,neww);
 51         midify_interval(m+1,r,rt<<1|1,m+1,nowr,neww);
 52     }
 53     update(rt);
 54 }
 55
 56 long long  query(int l,int r,int rt,int nowl,int nowr)
 57 {
 58     if(nowl<=l&&nowr>=r)
 59     {
 60         return sum[rt];
 61     }
 62     int m=(r+l)>>1;
 63     pushdown(l,r,m,rt);
 64     long long  ans=0;
 65     if(nowl<=m) ans+=query(l,m,rt<<1,nowl,nowr);
 66     if(nowr>m)ans+=query(m+1,r,rt<<1|1,nowl,nowr);
 67     return ans;
 68 }
 69
 70 int query_node(int l,int r,int rt,int nowrt)
 71 {
 72     if(l==r)
 73     {
 74         return sum[rt];
 75     }
 76     int m=(r+l)/2;
 77     sum[rt+rt]+=miku[rt]*(m-l+1);
 78     sum[rt+rt+1]+=miku[rt]*(r-m);
 79     miku[rt+rt]+=miku[rt];
 80     miku[rt+rt+1]+=miku[rt];
 81     miku[rt]=0;
 82     int ans=0;
 83     if(nowrt<=m) ans=query_node(l,m,rt<<1,nowrt);
 84     else if(nowrt>m)  ans=query_node(m+1,r,rt<<1|1,nowrt);
 85     return ans;
 86 }
 87
 88 int main()
 89 {
 90     int n;
 91     scanf("%lld",&n);
 92     for(int i=1;i<=n;i++)scanf("%lld",a+i);
 93     build(1,n,1);
 94     int m;
 95     scanf("%lld",&m);
 96
 97     for(int i=1;i<=m;i++)
 98     {
 99         scanf("%lld",&b);
100         if(b==1)
101         {
102             scanf("%lld%lld%lld",&c,&d,&e);
103             midify_interval(1,n,1,c,d,e);
104         }
105         if(b==2)
106         {
107             scanf("%lld%lld",&c,&d);
108             printf("%lld\n",query(1,n,1,c,d));
109         }
110     }
111     return 0;
112
113 }
时间: 2024-10-25 18:16:05

线段树标版的相关文章

SegmentTree-Complete 线段树完全版

线段树完全版关键词:延迟加载.懒标记Lazy Tag 单点更新的情况比较简单.请看 线段树基础版 下面说说区间更新的情况. 场景是这样的,还是刚刚的数,求区间的和. #define lson rt<<1 #define rson rt<<1|1 #define len (r-l+1) //(l,r)区间的长度 这次是区间更新,我们要用到区间的长度 建树 build和pushUp不变.我们把树建立好打印一下: [1]:36 [2]:26 [3]:10 [4]:15 [5]:11 [6

线段树普及版

一.简介线段树 \(ps\): 此处以询问区间和为例 线段树之所以称为"树",是因为其具有树的结构特性.线段树由于本身是专门用来处理区间问题的(包括\(RMQ\).\(RSQ\)问题等),所以其结构可以近似的看做一棵二叉查找树: \(emmmmm\)图是从网上偷的 对于每一个子节点而言,都表示整个序列中的一段子区间:对于每个叶子节点而言,都表示序列中的单个元素信息:子节点不断向自己的父亲节点传递信息,而父节点存储的信息则是他的每一个子节点信息的整合. 有没有觉得很熟悉?对,线段树就是分

杭电 HDU ACM 2795 Billboard(线段树伪装版)

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 14144    Accepted Submission(s): 6058 Problem Description At the entrance to the university, there is a huge rectangular billboard of

最大最小值(线段树基础版)

最大最小值 时间限制:1000 ms  |  内存限制:65535 KB 描述 给出N个整数,执行M次询问. 对于每次询问,首先输入三个整数C.L.R: 如果C等于1,输出第L个数到第R个数之间的最小值: 如果C等于2,输出第L个数到第R个数之间的最大值: 如果C等于3,输出第L个数到第R个数之间的最小值与最大值的和. (包括第L个数和第R个数). 输入 首先输入一个整数T(T≤100),表示有T组数据. 对于每组数据,先输入一个整数N(1≤N≤10000),表示有N个整数: 接下来一行有N个整

[您有新的未分配科技点]可,可,可持久化!?------可持久化线段树普及版讲解

最近跑来打数据结构,于是我决定搞一发可持久化,然后发现--一发不可收啊-- 对于可持久化数据结构,其最大的特征是"历史版本查询",即可以回到某一次修改之前的状态,并继续操作:而这种"历史版本查询"会衍生出其他一些强大的操作. 今天,我们主要讲解可持久化线段树.其实,它的另外一个名字"主席树"似乎更加为人所知(主席%%%). 主席树与普通的线段树相比,多出来的操作是在修改时复制修改的一条链,这个操作的过程大概长下面这样. 至于为什么要这样做-- 对

线段树完全版【代码集合

可能有些题要重写,先放这么多 单点更新 1.hdu1166敌兵布阵 1 #include <stdio.h> 2 #define maxn 200000 3 #include <algorithm> 4 using namespace std; 5 int qr, ql, v, x, l, n, ans; 6 int tree[maxn]; 7 void build(int o, int l,int r) { 8 if (l == r) { 9 scanf("%d&quo

线段树(区间修改+区间查询)

qwq , ylx 问我要一份线段树的版 , 可我线段树一直是10分钟 ,从不写版 ,qwq ,还是放一份版在这 . 题目见:http://poj.org/problem?id=3468 1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 const int inf = 1<<30 , maxn = 100000 + 11 ;

指针版线段树

只是作一下,以后必须得写数组版的...???(然而很好写? 哦对,唯一的好处就是内存少一点,没了.(coding量似乎并不会少很多?也不会多很多?雾) 还有很重要的一点就是慢...(尽管虽然没有慢多少?该卡还是卡?) 哎呀真是好纠结... 问了些神犇,似乎大家并不知道线段树还能用数组写... 呵呵... 然后看了一眼内存,指针严格开2n-1就好,而数组其实是要开4n的.... COJ上的数据太水了,数据只有大概... 所以呢.....要不我先用指针写几次再说? 不过是真心写着舒服. 1 #inc

求逆序对(线段树版)

一个序列a1,a2,a3...aN,求出满足:ai > aj 且 i < j 的个数. 一个最容易想到的方法就是枚举所有的i,j看看是否满足,显然是O(n^2)的复杂度.不够好. 可以这样考虑,开一个数组保存这n个数出现的位置和对应的次数,这个数组要开到a数组里最大的那个数MAX,也就是hash,初始状态数组里没有元素,每个数对应的个数都是0. 如果考虑第i个数,找到比它大的所有的数 的个数,查找的范围即 ai+1~MAX,这就是到i这个位置的逆序对的总和,接着把a[i]这个数添加到数组里,也