特殊做法类线段树

HDU 4578 Transformation(线段树+做了4天的神题+详解) Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations. Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation 阅读详情
有一类神奇的线段树,我们来总结一下。。。。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COGS  1272 AHOI  行星序列
一道看起来很简单的线段树,有两种操作,包括*k,+a,但经过思考我们发现,但操作顺序不同时(先乘后加还是先加后乘),所以我们统一为一种操作(*k => *k+0  +a => *1+a) 于是水过。。。code:
#include<iostream>
#include<cstdio>
#include<cstring>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
long long node[400001],a[100001];
int n,p,m;
long long  delta[400001][2],ans;
void updata(int i)
{
	node[i]=(node[i<<1]+node[i<<1|1])%p;
}
void build(int i,int l,int r)
{
	delta[i][0]=1;
	delta[i][1]=0;
	if (l==r)
	  {
	    node[i]=a[l]%p;
	    return;
	  }
	build(lch); build(rch);
	updata(i);
}
void paint(int i,int l,int r,long long k,long long a)
{
	int t;
	a=a%p;  k=k%p; t=(r-l+1)%p; 
	node[i]=((node[i]*k)%p+(a*t)%p)%p;
	delta[i][0]=(delta[i][0]*k)%p;
	delta[i][1]=((delta[i][1]*k)%p+a)%p;
}
void pushdown(int i,int l,int r)
{
	paint(lch,delta[i][0],delta[i][1]);
	paint(rch,delta[i][0],delta[i][1]);
	delta[i][0]=1; delta[i][1]=0;
}
void insert(int i,int l,int r,int x,int y,long long a,int kind)
{
	if (x<=l&&y>=r)
	  {
	  	if (kind==2)
	      paint(i,l,r,1,a);
	    if (kind==1)
	      paint(i,l,r,a,0);
	    return;
	  }
	pushdown(i,l,r);
	if (x<=mid) insert(lch,x,y,a,kind);
	if (y>mid) insert(rch,x,y,a,kind);
	updata(i);
}
void query(int i,int l,int r,int x,int y)
{
	if (x<=l&&y>=r)
	  {
	    ans=(node[i]+ans)%p;
		return;   
	  }
	pushdown(i,l,r);
	if (x<=mid) query(lch,x,y);
	if (y>mid) query(rch,x,y);
}
int main()
{
	freopen("seqb.in","r",stdin);
	freopen("seqb.out","w",stdout);
	int i,kind,t,g,c;
	scanf("%d%d",&n,&p);
	for (i=1;i<=n;++i)
	 scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&m);
	for (i=1;i<=m;++i)
	  {
	    scanf("%d",&kind);
	    if (kind==1||kind==2)
	      {
	      	c=c%p;
	        scanf("%d%d%d",&t,&g,&c);
			insert(1,1,n,t,g,c,kind); 
	      }
	    if (kind==3)
	      {
	        scanf("%d%d",&t,&g);
	        ans=0; query(1,1,n,t,g);
	        printf("%lld\n",ans);
	      }
	  }
	fclose(stdin);
	fclose(stdout);
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COGS  三元数对&&数列
      统计在某数之前比某数小和某数之后比某数小(或大)的个数,思路很奇特,以数字为节点建树,然后在线单点修改,区间求值。。。
 三元数对(离散化)code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
int node[200000],n;
int a[30001],b[30001];
int minn[30001];
int ans;
long long sum;
void updata(int i)
{
	node[i]=node[i<<1]+node[i<<1|1];
}
void insert(int i,int l,int r,int x)
{
	if (l==r&&l==x)
	  {
	    node[i]+=1;
	    return;
	  }
	if (x<=mid) insert(lch,x);
	else insert(rch,x);
	updata(i);
}
void query(int i,int l,int r,int x,int y)
{
	if (x<=l&&y>=r)
	  {
	    ans+=node[i];
		return;     
	  }
	if (x<=mid) query(lch,x,y);
	if (y>mid) query(rch,x,y);
}
int main()
{
	int i,size;
	freopen("three.in","r",stdin);
	freopen("three.out","w",stdout);
	scanf("%d",&n);
	sum=0;
	for (i=1;i<=n;++i)
	  {
	    scanf("%d",&a[i]);
	    a[i]+=2;
	    b[i]=a[i];
	  }
	sort(b+1,b+n+1);
	size=unique(b+1,b+n+1)-b-1;
	for (i=1;i<=n;++i)
	    a[i]=upper_bound(b+1,b+size+1,a[i])-b;
	size++;
	memset(node,0,sizeof(node));
	for (i=1;i<=n;++i)
	  {
	    insert(1,1,size,a[i]);
	    if (i>1)
	      {
	        ans=0;
	        query(1,1,size,1,a[i]-1);
	        minn[i]=ans;
	      }
	  }
	memset(node,0,sizeof(node));
	for (i=n;i>=1;--i)
	  {
	    insert(1,1,size,a[i]);
	    if (i<n)
	      {
	        ans=0;
	        query(1,1,size,a[i]+1,size);
	        if (i>1)
	          sum+=ans*minn[i];
	      }
	  }
	printf("%lld\n",sum);
	fclose(stdin);
	fclose(stdout);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TYVJ 1728 普通平衡树
一道著名的平衡树练习题,我们考虑它的线段树做法(做死了。。。),首先离散化(为了输出原数搞一个类似映射的东西),然后以数为节点建立线段树,然后blabla乱搞就好了(蒟蒻的算法常数很大,很大) code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
int node[400001],n;
struct hp{
	int kind,x;
}opt[100001];
int b[100001];
int f[100001],ans,rank,ansi;
void updata(int i)
{
	node[i]=node[i<<1]+node[i<<1|1];
}
void insert(int i,int l,int r,int x,int a)
{
	if (l==r&&l==x)
	  {
	    node[i]+=a;
	    return;
	  }
	if (x<=mid) insert(lch,x,a);
	else insert(rch,x,a);
	updata(i);
}
void querynum(int i,int l,int r,int x)
{
	if (l==r&&l==x)
	  {ansi=i; ans++; return;}
	if (x<=mid)
	  querynum(lch,x);
	else
	  {
	  	ans+=node[i<<1];
	    querynum(rch,x);
	  }
}
void queryx(int i,int l,int r,int x)
{
	if (l==r&&rank<=x&&rank+node[i]>=x)
	  {
	    ans=l;
		return; 
	  } 
	if (rank+node[i<<1]>=x)
	  queryx(lch,x);
	else
	  {
	    rank+=node[i<<1];
		queryx(rch,x); 
	  } 
}
int main()
{
	int t,i,size;
	freopen("phs.in","r",stdin);
	freopen("phs.out","w",stdout);
	scanf("%d",&n);
	for (i=1;i<=n;++i)
	  {
	    scanf("%d%d",&opt[i].kind,&opt[i].x);
	    b[i]=opt[i].x;
	  }
	sort(b+1,b+n+1);
	size=unique(b+1,b+n+1)-b-1;
	for (i=1;i<=n;++i)
	  {
	    t=lower_bound(b+1,b+size+1,opt[i].x)-b;
		f[t]=opt[i].x;
		opt[i].x=t;  
	  }
	for (i=1;i<=n;++i)
	  {
        if (opt[i].kind==1)
          insert(1,1,size,opt[i].x,1);
        if (opt[i].kind==2)
          insert(1,1,size,opt[i].x,-1);
        if (opt[i].kind==3) 
          {
            ans=0;
            querynum(1,1,size,opt[i].x);
            printf("%d\n",ans);
          }
        if (opt[i].kind==4)
          {
          	rank=0; 
            queryx(1,1,size,f[opt[i].x]);
            printf("%d\n",f[ans]); 
          }
        if (opt[i].kind==5)
          {
          	ans=0;
          	querynum(1,1,size,opt[i].x);
            rank=0;
            queryx(1,1,size,ans-1);
            printf("%d\n",f[ans]);
          }
        if (opt[i].kind==6)
          {
		    ans=0; 
            querynum(1,1,size,opt[i].x);
            rank=0; 
            queryx(1,1,size,ans+node[ansi]);
            printf("%d\n",f[ans]);
          }
	  }
	fclose(stdin);
	fclose(stdout);
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                                                                                                                                                  Lcomyn
线段树详解(包含加法线段树、乘法线段树及区间根号线段树,简单易懂) 线段树及简单应用。 阅读详情

相关推荐

EDK2多平台编译实战:从树莓派到RK3399的UEFI固件构建

本文提供了从树莓派到RK3399的EDK2多平台编译实战指南。详细介绍了UEFI固件构建的环境搭建、交叉编译配置、平台描述文件修改及常见问题排查,帮助开发者掌握为不同ARM架构硬件构建标准化启动固件的核心技能。

weixin_29193259的博客 836

【数据结构】若干线段树写法(实现方法有代码)总结及各种特殊线段树思想

目录 背景 线段树 本人习惯的线段树 主流的线段树 动态开点线段树 可持久化线段树 k小值版经典主席树 区间修改主席树 其他好东西 背景 明天JSOI2019省选。 将线段树理了一遍。本文主要包括:本人习惯的线段树写法,主流的线段树写法,类主席树的线段树写法,k小值版经典主席树,区间修改主席树。其中除了第四种,其他都支持区间加与区间求和。 在文末提...

czyarl的博客 1336

【黑马点评优化】3-压测秒杀接口,算出性能塌陷区,之后用sentinel实现秒杀接口限流

【黑马点评优化】3-压测秒杀接口,算出性能塌陷区,之后用sentinel实现秒杀接口限流

m0_52031708的博客 3570

线段树的特殊运用

线段树有一种用法,是用多个值域线段树实现一些操作:1、合并2、分裂【分出前k小的数3、查询K小尝试用最暴力的方法实现合并暴力实现的复杂度分析:分裂操作在线段树上的路径和查询K小的路径长度都是log n的,所以分裂和找k小的复杂度是每次严格log n的,且分裂一次最多增加log n个点合并实现方法具体如下↓void merge(root1,root2){//合并到root1上    if 两颗左子树...

zawedx的博客 9240

从零开始:如何用Python手绘波特图并分析电路稳定性

本文详细介绍了如何使用Python绘制波特图并分析电路稳定性,涵盖从基础理论到实际应用的完整流程。通过NumPy和Matplotlib实现频域分析,包括RC低通滤波器和RLC带通滤波器的案例,以及相位裕度计算等高级技巧,为电子工程师提供了一套高效的电路分析解决方案。

hhh00的博客 371

【上海大学计算机组成原理实验报告】七、程序转移机制

学习实现程序转移的硬件机制//掌握堆栈寄存器的使用//手动方式实现子程序调用转移过程//手动方式实现子程序返回转移过程//编程实现`OUT`寄存器交替显示`11`和`55`//若要求`11`和`55`各显示`50`次后停机,应该如何修改程序?//根据实验指导书的相关内容,实验箱系统的程序转移硬件机制在于,当`LDPC`有效时,如果此时`DUBS`上的值就是转移的目标地址,则此目标地址被打入`PC`,从而实现程序的转移;若`LDPC`为`0`是附带条件的,就形成“条件转移”。

HackerKevon的博客 2473

线段树更进一步的运用

区间修改 线段树除了点修改之外还有更多的作用 Add(l,r,v):把a[l],a[l+1],a[l+2]…a[r]中所有元素加v Query(l,r):计算子序列a[l],a[l+1],…,a[r]的元素和,最小值和最大值当然如果你想让你的代码拥有更多的黑科技气息(附带运算速度加成),你可以采用 位运算 这种优(zhuang)秀(bi)的技巧定义线段树需要维护的区间和,最小值和最大值分别

yangbowen2的博客 339

FOC观测器之龙伯格观测器

状态观测器: 理论依据:根据控制理论,如果一个系统能够完全通过其检测到的输出值来重构其系统状态,则认为该系统是可观测的。其作用于无传感器转子的位置和速度的检测反馈,再作用到PARK逆变换和转矩磁链控制上。 Luenberger观察器原理图: Luenberger观测器的离散化: (其观测器的闭环参数为经验验证值) 引入估测电流( iα,iβ )的反馈值并离散化(T 为采样时间),可得...

ShawnChan的博客 2万+

线段树各种神操作

接下来就到了大名鼎鼎的线段树了! 线段树是一种维护区间可加信息的数据结构 传说中无所不能,神通广大的它到底有什么本事呢 请看今日说法 技能一 区间最大值  稀有程度 普通 RMQ问题,是各种数据结构的裸题,也不一定非要用线段树做,常数很大,ST表显然是一个很好的选择 但是就是一道练手题 Code #include&lt;cstdio&gt; #include&lt;iostrea...

Richard__Luan的博客 492

生成式引擎优化(GEO)全流程解析

生成式引擎优化(GEO)已成为AI时代数字营销新趋势,通过优化企业内容以提升在AI生成答案中的引用率。本文系统梳理了GEO优化的完整流程,包括:1)前期准备与市场调研;2)数据治理与知识库构建;3)模型适配与算法优化;4)内容权威性建设;5)本地化营销;6)效果监测与优化。研究显示,实施GEO的企业AI曝光率提升62%,转化率增长2.3倍。未来GEO将向多模态内容、实时个性化、垂直场景深化方向发展。企业需建立动态知识图谱,采用结构化数据标记,持续优化内容策略,以在AI搜索时代获取流量优势。

解锁AI流量新红利!🚀 GEO优化(生成引擎优化)助您掌控AI搜索,让AI成为您的品牌最佳代言人! 3246

【iOS开发】dyld: Symbol not found: ___chkstk_darwin 问题解决

【iOS开发】dyld: Symbol not found: ___chkstk_darwin 问题解决 Xcode 13.2.1 运行到iOS12.x版本上崩溃报错如下:dyld: Symbol not found: ___chkstk_darwin dyld: Symbol not found: ___chkstk_darwin Referenced from: /private/var/containers/Bundle/Application/A424CEFD-51DB-450E-9D62-B8

wm9028的专栏 6563

【算法】线段树

几乎是算法竞赛最常用的数据结构了,它主要用于(要求满足结合律)。与树状数组相比,它可以实现的,还可以同时(加、乘),更具通用性。如题,已知一个数列,你需要进行下面两种操作:1.将某区间每一个数加上x2.求出某区间每一个数的和第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

weixin_73366312的博客 1808

Windows2008使用-解决漏洞-CVE-2010-2730

随着硬件的升级,操作系统也逐渐进行了版本更新。目前阶段,Windows2016Server、Windows2022Server逐渐成为了以Windows系列的服务器平台系统。对于有些应用而言,由于其业务的固定,可能仍只能运行在Windows2008Server或者Windows2012Server上。有时候我们为安全需要,需要将相关的操作系统涉及的漏洞做修复。最近碰到在一个Windows2008R2 的操作系统漏洞CVE-2010-2730,一顿操作,终于找到了合适的方案,这里分享给大家。

mystonelxj的博客 2314

线段树算法

以下内容来自百度线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。1.区间查询:查询某个区间内的信息。例如,查询某个区间内的最大值、最小值、总和等等。2.区间修改:对某个区间内的数值进行更新。

xyzcoolplayer的博客 1629

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

线段树求周长求交面积的做法

求周长的做法是对每个段,用线段树计算出不相交的区间个数,至于求区间个数,有点像扫描线的做法,也是先排序,排序之后就是求括号序列有多少个区间,很有技巧。然后就是段的长度*区间个数*2,然后对矩形坐标进行关于y=x对称,再做一次就是完整的周长了。受求周长做法的启发,可以得到求矩形交面积的做法,需要一个一维线段树,记录x方向线段的信息,还要一个二维线段树记录各部分是否被覆盖,一维线段树在某线段处ad

jollyjumper的专栏 1286

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

线段树快速上手

线段树是高效查询数组某区间的特殊值的高级数据结构。底层适用数组来实现,但逻辑上是二叉树结构,因此它的更新和查询的时间复杂度都是OlogNO(logN)OlogN。(建立线段树的时间复杂度是ONO(N)ON这里提到的区间特殊值有很多,可以是区间最值,可以是区间和,也可以是区间GCD(最大公约数)等等。因此它的应用非常广泛。

HYY的博客 959

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

线段树基础(上)

线段树基础。

wanglianda2007的博客 1234

【算法进阶详解】线段树应用

本文不讲解线段树的基础理论,而是讲解线段树的应用,如线段树优化 DP,扫描线。如有问题欢迎指出。

mkx2023275的博客 1136

特殊数据结构-线段树

线段树的定义: 二叉搜索树,多用于解决区间问题,但不代表只能解决区间问题。 思考三个问题: 节点存什么? 节点下标是什么? 如何建树? 给出一个样例讲解节点的存储信息。 结论如下: 每个叶子结点的值就是数组的值,每个非叶子结点的度都为二,且左右两个孩子分别存储父亲一半的区间。每个父亲的存储的值也就是两个孩子存储的值的最大值。 在实际操作过程中一般不会考虑采用二叉树的链表结构存储线段树,因为无法再O(1)时间复杂度获取节点。故一般采取数组来进行存储。 其中绿色下标代表的就是数组下标。 其实完全可以发现

带你飞 167

扫描线总结【线段树特殊性质,没有pushdown、query操作】

扫描线 题意 多个矩阵求交集,线段树的特殊操作,非常特殊的情况,一堆证明之后,就没有pushdown操作。 没有pushdown操作,也没有query操作,直接tr[1].len. 亚特兰蒂斯 由于点可能有小数,先l、离散化为整数,这里的线段树存的是一个区间:【L,R),左闭右开的区间。 换句话:线段树存的是第几个小区间,那么操作(l,r)的话,对线段树操作:l–r-1就够了,(存的不是点,是小区间,小区间比点的数量少1) 另外,也不需要query()函数,之间调用tr[1].len,返回线段长度 代码 #

谁是凶手1703 396

权值线段树

权值线段树什么是权值线段树权值线段树有什么用权值线段树的构建与查询 什么是权值线段树 权值线段树是线段树的一种,但是它与线段树不同; 线段树的每个结点是用来维护一段区间的最大值或总和; 而权值线段树的每个结点储存的一段区间有多少个数; 权值线段树有什么用 权值线段树主要用来查询区间第k大或者第k小的值; 权值线段树的构建与查询 现在有一个数组x[10]={1,5,3,2,4,8,3,2,1,1}...

Darge. 871

线段树(区间树)Segment Tree

线段树(区间树) Segment Tree

底层码农 6538

树套树之线段树套线段树(BZOJ3110、洛谷P3332)

线段树可以维护一个序列。当需要维护一个矩阵(即二维平面)内的数值,或者有什么奇怪的区间操作时,就需要用到二维线段树,也就是线段树“套上”线段树。

forezxl的博客 1408

HDU 4107 Gangster(线段树 特殊懒惰标记)

两种做法。 第一种:标记区间最大值和最小值,若区间最小值>=P,则本区间+2c,若区间最大值<P,则本区间+c。非常简单的区间更新。 最后发一点牢骚:最后query查一遍就行,我这个2B竟然写了个for循环每个点查了一遍orz……然后比赛的时候就一直TLE还查不出原因……感觉线段树对我就像个诅咒一样,每场必不出,不管是多么简单的线段树,都会错在千奇百怪的地方……说到底也不...

aegt43853的博客 164

线段树练习题集

线段树题目整合 1.hdu1166 敌兵布阵 更新节点,区间求和。 2.hdu1754 I Hate It 更新节点,区间最值. .3.hdu1698 Just a Hook 成段更新,总区间求和. .4.hdu1394 Minimum Inversion Number 更新节点,区间求和 .5.hdu1779(这个爆炸了,别做了) 成段更新,区间最值 .6.pku...

UncleJokerly 2471

线段树讲解

一.线段树概念及说明 线段树(Segment Tree):线段树是一种二叉搜索树,其最擅长的是进行区间处理操作,通常树上的每个节点都维护一个区间,线段树树根维护的是整个区间。每个子节点维护的是其父节点所维护区间二等分后的两个区间的其中之一。 线段树节点的结构如图1所示: 图1 给出一个【1,11】的区间,构建线段树,如图2所示。 图2 通常构建【1,N】的线段树

温姑娘的博客 1735
上一篇: 差分序列应用
下一篇: 双向广搜(DBFS)
Lcomyn
博客等级 码龄12年 14粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值