线段树模板合集(CodeVS1080 1081 1082 4597)Pascal代码

var sum,flag,a,mn:array[0..800000] of int64;
var n,m,x,y,z,c:int64;
var i:longint;
function max(a,b:int64):int64;
begin
  if a>b then exit(a);exit(b);
end;
function min(a,b:int64):int64;
begin
  if a<b then exit(a);exit(b);
end;
procedure change(h:int64);
begin
  sum[h]:=sum[h<<1]+sum[h<<1+1];
  mn[h]:=min(mn[h<<1],mn[h<<1+1]);{max}
end;
procedure build(l,r,h:int64);//建树
var m:int64;
begin
  if l=r then begin sum[h]:=a[l];mn[h]:=a[l];exit;end;
  m:=(l+r)>>1;build(l,m,h<<1);build(m+1,r,(h<<1) or 1);
  change(h);
end;
procedure add(x,c,l,r,h:int64);//单点修改(加法运算){括号内为减法运算}
var m:int64;
begin
  if l=r then begin inc(sum[h],c);{dec}inc(mn[h],c);{dec}exit;end;
  m:=(l+r)>>1;if x<=m then add(x,c,l,m,h<<1) else add(x,c,m+1,r,(h<<1) or 1);
  change(h);
end;
procedure pushdown(h,l,r:int64);//下推(加法运算){括号内为减法运算}
begin
  if flag[h]<>0 then
  begin
    inc(flag[h<<1],flag[h]);
    inc(flag[(h<<1) or 1],flag[h]);
    inc(sum[h<<1],flag[h]*l);{dec}
    inc(sum[(h<<1) or 1],flag[h]*r);{dec}
    inc(mn[h<<1],flag[h]);{dec}
    inc(mn[(h<<1) or 1],flag[h]);{dec}
    flag[h]:=0;
  end;
end;
procedure range_add(x,y,c,l,r,h:int64);//区间相加{括号内为相减}
var m:int64;
begin
  if (x<=l) and (r<=y) then
  begin
    inc(sum[h],c*(r-l+1));{dec}
    inc(mn[h],c); {dec}
    inc(flag[h],c);
    exit;
  end;
  m:=(l+r)>>1;pushdown(h,m-l+1,r-m);
  if x<=m then range_add(x,y,c,l,m,h<<1);
  if y>m then range_add(x,y,c,m+1,r,(h<<1) or 1);
  change(h);
end;
function worksum(x,y,l,r,h:int64):int64;//区间求和
var m,ans:int64;
begin
  if (x<=l) and (r<=y) then exit(sum[h]);
  m:=(l+r)>>1;pushdown(h,m-l+1,r-m);ans:=0;
  if x<=m then inc(ans,worksum(x,y,l,m,h<<1));
  if y>m then inc(ans,worksum(x,y,m+1,r,(h<<1) or 1));
  exit(ans);
end;
function workmin(x,y,l,r,h:int64):int64;{max}//区间求最小值{括号内为最大值}
var m,ans:int64;
begin
  if (x<=l) and (r<=y) then exit(mn[h]);
  m:=(l+r)>>1;pushdown(h,m-l+1,r-m);
  ans:=maxlongint;{-maxlongint}
  if x<=m then ans:=min(ans,workmin(x,y,l,m,h<<1));{max}
  if y>m then ans:=min(ans,workmin(x,y,m+1,r,(h<<1) or 1));{max}
  exit(ans);
end;
procedure input;
begin
  read(n);for i:=1 to n do read(a[i]);build(1,n,1);
end;
procedure p1080;
begin
  input;read(m);
  for i:=1 to m do
  begin
    read(x,y,z);
    if x=1 then add(y,z,1,n,1);
    if x=2 then writeln(worksum(y,z,1,n,1));
  end;
end;
procedure p1081;
begin
  input;read(m);
  for i:=1 to m do
  begin
    read(x);
    if x=1 then begin read(y,z,c);range_add(y,z,c,1,n,1);end;
    if x=2 then begin read(y);writeln(worksum(y,y,1,n,1));end;
  end;
end;
procedure p1082;
begin
  input;read(m);
  for i:=1 to m do
  begin
    read(x);
    if x=1 then begin read(y,z,c);range_add(y,z,c,1,n,1);end;
    if x=2 then begin read(y,z);writeln(worksum(y,z,1,n,1));end;
  end;
end;
procedure p4597;
var n,q,l,r,p:int64;
var i:longint;
var c:char;
begin
  readln(n,q);
  for i:=1 to n do read(a[i]); readln;
  build(1,n,1);
  for i:=1 to q do
   begin
    read(c);
    if c=‘M‘ then begin readln(l,r);;writeln(workmin(l,r,1,n,1));end;
    if c=‘S‘ then begin readln(l,r);writeln(worksum(l,r,1,n,1));end;
    if c=‘P‘ then begin readln(l,r,p);range_add(l,r,p,1,n,1);end;
   end;
end;
begin
  //主程序
end.

  

时间: 2024-10-06 00:41:23

线段树模板合集(CodeVS1080 1081 1082 4597)Pascal代码的相关文章

UVALive 4730 Kingdom 线段树+并查集

题目链接:点击打开链接 题意见白书P248 思路: 先把读入的y值都扩大2倍变成整数 然后离散化一下 用线段树来维护y轴 区间上每个点的 城市数量和联通块数量, 然后用并查集维护每个联通块及联通块的最大最小y值,还要加并查集的秩来记录每个联通块的点数 然后就是模拟搞.. T^T绝杀失败题..似乎数组开小了一点就过了,== #include<stdio.h> #include<math.h> #include<vector> #include<string.h>

线段树模板(结构体)

线段树研究了两天了,总算有了点眉目,今天也把落下的题,补了一下. 贴一份线段树模板 线段树的特点: 1. 每一层都是区间[a, b]的一个划分,记 L = b - a 2. 一共有log2L层 3. 给定一个点p,从根到叶子p上的所有区间都包含点p,且其他区间都不包含点p. 4. 给定一个区间[l; r],可以把它分解为不超过2log2 L条不相交线段的并. 总结来说:线段树最近本的应用是4点: 1.单点更新:单点替换.单点增减 2.单点询问 3.区间询问:区间之和.区间最值 4.区间更新:区间

[ACM] 线段树模板

#include<iostream> #include<cmath> using namespace std; #define maxn 200005 class Node{ public: int l,r; int add;//附加值 int sum; }node[maxn]; int getRight(int n){//获得满足2^x>=n的最小x[从0层开始,给编号获得层数] return ceil(log10(n*1.0)/log10(2.0)); } void bu

[POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]

可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <vector> using namespace std; int n,q,tot,a[110000]; in

hdu 4819 二维线段树模板

/* HDU 4819 Mosaic 题意:查询某个矩形内的最大最小值, 修改矩形内某点的值为该矩形(Mi+MA)/2; 二维线段树模板: 区间最值,单点更新. */ #include<bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 1010; int N, Q; struct Nodey { int l, r; int Max, Min; }; int locx[MAXN], l

【HDU 4819】Mosaic 二维线段树模板

二维线段树的模板题,和一维一样的思路,更新的时候注意一下细节. 存模板: /* 二维线段树模板整理 */ #include<cstdio> #include<algorithm> using namespace std; #define lson (pos<<1) #define rson (pos<<1|1) const int maxn = 805; const int INF = (1 << 30); int n; int posX[max

UVA 1455 - Kingdom(线段树+并查集)

UVA 1455 - Kingdom 题目链接 题意:给定一些城市坐标点,连在一起的城市称为一个州,现在用两种操作,road表示把城市a,b建一条路,line表示询问一个y轴上穿过多少个州,和这些州共包含多少个城市 思路:利用并查集维护每个州的上界和下界还有城市个数,然后每次加进一条路的时候,根据两个集合的位置可以处理出区间的州和城市数如何进行加减,然后利用线段树搞就可以了 代码: #include <cstdio> #include <cstring> #include <

学渣乱搞系列之Tarjan模板合集

学渣乱搞系列之Tarjan模板合集 by 狂徒归来 一.求强连通子图 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <climits> 7 #include <vector> 8 #include <queue> 9 #incl

LA 2191电位计(线段树模板题)

线段树模板题,没啥好说的.....注意输出是case之间空一行就行.........之前一直没注意,一直wa 代码如下: #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #includ