洛谷P9388 [THUPC 2023 决赛] 先人类的人类选别(主席树+权值线段树)

题目

思路来源

P9388 [THUPC 2023 决赛] 先人类的人类选别 - 违规用户名FkZyA0!2 的博客 - 洛谷博客

题解

这个题是2023ccpc深圳热身赛的题目,也是thupc2023决赛的题目,

学弟问了一下,于是就乱搞了一下,搞了很久才a,赛后一看题解直呼自己sb

不过主席树和权值线段树两棵树叠加在一起的操作也确实很少见,也记录一下吧

正解

观察到操作序列一定时,操作顺序对答案并没有影响。

将询问[l,r]拆成前缀和作差,也就是[1,r]减去[1,l-1]

在时刻q时,对于一个前缀区间[1,x],

操作的本质,相当于把[1,x]原来的数和[1,q]询问中出现的数放在一起,

取最小的q个值丢给后面

想求[1,x]的和,也就是求得总和和最小的q个值的和即可,无需关注具体位置

所以可以将原序列中的数维护在一棵主席树上,

将询问中出现的数,在线维护在一棵权值线段树上,

由于主席树sum可以作差的性质,那么两棵树叠在一起也是可以作和的

查询的时候,按照值域,在两棵树叠在一起的树上一起跑即可

乱搞AC(五棵线段树)

这个操作是在维护一个冒泡非严格降序序列,

考虑主要维护三棵树,一棵A线段树是原始序列中不在冒泡序列里的,

另两棵,B线段树维护冒泡序列的位置,C线段树维护权值线段树当前有哪些值

于是就需要求,每个值是在哪个时刻被扔进冒泡序列里的,

对于一个数x,记其左侧<=x的数的个数为y,那么其rank为y+1

那么只有当询问中出现第y+1个>x的数时,

数x才会被拔高,也就是会被扔进冒泡序列里,

记第i个数被拔高的时刻是dfn[i],考虑怎么求

一开始是整体二分两个log求的dfn,

也就是按时间序把n个位置时间序的m个时间节点放一起二分

结果两个logT了,

想了一会,改成了现在这个1log动态全局删点的,

先将n个位置按值从小到大排增序,如果值相同,从左到右排增序,

线段树上每个位置的初始值是其左侧小于等于这个数的数的个数,

询问中每出现一个数x,就对小于x的位置区间减1,

当有位置被减到0时,说明在本轮被拔高,

加入对应时刻的dfn,动态删点给删掉即可

所以需要维护区间最小值,动态删点时,给单点置为INF

那么,除了图中的ABC三棵树外,

一棵线段树用于求每个数的rank,另一棵线段树用于区间减1和动态删点

所以最后是五棵线段树,降成了O(nlogn),

以为3s时限比较稳,但是常数巨大,开O2跑了2.99s,属实没绷住

代码1(正解)

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long
#define maxn 500005
int n,m;
int a[maxn],suf[maxn],root[maxn],rota,cnt;
struct node {int ls,rs,sum,siz;
} f[maxn*30];
int Update(int l,int r,int pre,int head) {int rt=++cnt;f[rt]=f[pre];f[rt].siz++;f[rt].sum+=head;if (l==r) return rt;int mid=l+r>>1;if (head<=mid) f[rt].ls=Update(l,mid,f[rt].ls,head);else f[rt].rs=Update(mid+1,r,f[rt].rs,head);return rt;
}
void Update2(int l,int r,int &rt,int head) {if (!rt) rt=++cnt;f[rt].siz++,f[rt].sum+=head;if (l==r) return ;int mid=l+r>>1;if (head<=mid) Update2(l,mid,f[rt].ls,head);else Update2(mid+1,r,f[rt].rs,head);
}
int Query(int l,int r,int rt1,int rt2,int k) {if (l==r) return k*l;int mid=l+r>>1,siz=f[f[rt1].ls].siz+f[f[rt2].ls].siz;if (siz>=k) return Query(l,mid,f[rt1].ls,f[rt2].ls,k);else return f[f[rt1].ls].sum+f[f[rt2].ls].sum+Query(mid+1,r,f[rt1].rs,f[rt2].rs,k-siz);
}
signed main(void) {int i,x,l,r,sum=0;scll(n);scll(m);for (i=1; i<=n; i++) scll(a[i]),suf[i]=suf[i-1]+a[i];for (i=1; i<=n; i++) {root[i]=Update(1,n,root[i-1],a[i]);}for (i=1; i<=m; i++) {scll(x);scll(l);scll(r);sum+=x;Update2(1,n,rota,x);int tmp1=suf[l-1]+sum-Query(1,n,root[l-1],rota,i);int tmp2=suf[r]+sum-Query(1,n,root[r],rota,i);printf("%lld\n",tmp2-tmp1);}return 0;
}

代码2(乱搞AC)

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=5e5+10,INF=0x3f3f3f3f;
int n,m,id[N],a[N];
vector<int>dfn[N];
P b[N];
ll rk[N],ans;
struct qeury{int x,l,r;void rd(){sci(x),sci(l),sci(r);}
}e[N];
struct segtree{int n;struct node{int l,r;ll v,s;}e[N<<2];#define l(p) e[p].l#define r(p) e[p].r#define v(p) e[p].v#define s(p) e[p].svoid up(int p){v(p)=v(p<<1)+v(p<<1|1);s(p)=s(p<<1)+s(p<<1|1);}void bld(int p,int l,int r){l(p)=l;r(p)=r;s(p)=v(p)=0;if(l==r){return;}int mid=l+r>>1;bld(p<<1,l,mid);bld(p<<1|1,mid+1,r);up(p);}void init(int _n){n=_n;bld(1,1,n);}void chg(int p,int x,int v){if(l(p)==r(p)){v(p)=v;return;}int mid=l(p)+r(p)>>1;chg(p<<1|(x>mid),x,v);up(p);}void add(int p,int x,int v){if(l(p)==r(p)){v(p)+=v;s(p)+=1ll*l(p)*v;return;}int mid=l(p)+r(p)>>1;add(p<<1|(x>mid),x,v);up(p);}ll cnt(int p,int ql,int qr){if(ql>qr)return 0;if(ql<=l(p)&&r(p)<=qr)return v(p);int mid=l(p)+r(p)>>1;ll res=0;if(ql<=mid)res+=cnt(p<<1,ql,qr);if(qr>mid)res+=cnt(p<<1|1,ql,qr);return res;}ll topK(int p,int k){if(k<=0)return 0;if(l(p)==r(p))return 1ll*k*l(p);if(v(p<<1|1)>=k)return topK(p<<1|1,k);return s(p<<1|1)+topK(p<<1,k-v(p<<1|1));}
}tr[4];
struct segtree2{int n;struct node{int l,r,v,c;}e[N<<2];#define l(p) e[p].l#define r(p) e[p].r#define v(p) e[p].v#define c(p) e[p].cvoid up(int p){v(p)=min(v(p<<1),v(p<<1|1));}void bld(int p,int l,int r){l(p)=l;r(p)=r;v(p)=INF;c(p)=0;if(l==r){return;}int mid=l+r>>1;bld(p<<1,l,mid);bld(p<<1|1,mid+1,r);up(p);}void psd(int p){if(c(p)){v(p<<1)+=c(p);c(p<<1)+=c(p);v(p<<1|1)+=c(p);		c(p<<1|1)+=c(p);c(p)=0; }}void init(int _n){n=_n;bld(1,1,n);}void chg(int p,int x,int v){if(l(p)==r(p)){v(p)=v;return;}int mid=l(p)+r(p)>>1;psd(p);chg(p<<1|(x>mid),x,v);up(p);}void del(int p,int x){if(l(p)==r(p)){v(p)=INF;return;}int mid=l(p)+r(p)>>1;psd(p);del(p<<1|(x>mid),x);up(p);}void add(int p,int ql,int qr,int v){if(ql>qr)return;if(ql<=l(p)&&r(p)<=qr){v(p)+=v;c(p)+=v;return;}psd(p);int mid=l(p)+r(p)>>1;if(ql<=mid)add(p<<1,ql,qr,v);if(qr>mid)add(p<<1|1,ql,qr,v);up(p);}int fmn(int p){//printf("p:%d vp:%d vlp:%d vrp:%d\n",p,v(p),v(p<<1),v(p<<1|1));if(v(p)>0)return 0;if(l(p)==r(p))return l(p);int mid=l(p)+r(p)>>1;psd(p);if(v(p<<1)<=0)return fmn(p<<1);else return fmn(p<<1|1);}
}seg;
int main(){sci(n),sci(m);rep(i,0,3)tr[i].init(n);seg.init(n);rep(i,1,n){sci(a[i]);tr[0].chg(1,i,a[i]);tr[3].add(1,a[i],1);rk[i]=tr[3].cnt(1,1,a[i]);//seg.chg(1,i,rk[i]);b[i]=P(a[i],i);//printf("i:%d rk:%d\n",i,rk[i]);}sort(b+1,b+n+1);rep(i,1,n){seg.chg(1,i,rk[b[i].se]);//printf("i:%d bi.se:%d rk:%d\n",i,b[i].se,rk[b[i].se]);}b[n+1]=P(n+1,0);rep(i,1,m){e[i].rd();int p=lower_bound(b+1,b+n+2,P(e[i].x,0))-b;p--;//printf("i:%d p:%d\n",i,p);seg.add(1,1,p,-1);int p2;while((p2=seg.fmn(1))>0){//printf("i:%d p2:%d\n",i,p2);dfn[i].pb(b[p2].se);seg.del(1,p2);}}rep(i,1,m){int x=e[i].x,l=e[i].l,r=e[i].r;for(auto &p:dfn[i]){//printf("i:%d p:%d\n",i,p);tr[0].add(1,p,-a[p]);tr[1].add(1,p,1);tr[2].add(1,a[p],1);}tr[2].add(1,x,1);ans=tr[0].cnt(1,l,r);int k1=tr[1].cnt(1,1,l-1);int k2=tr[1].cnt(1,1,r);ans+=tr[2].topK(1,k2)-tr[2].topK(1,k1);printf("%lld\n",ans);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/189874.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux ____03、文件类型、属性、修改文件属性(更改文件权限)(命令)

文件类型、属性、修改文件属性 一、文件类型二、文件属性三、修改文件属性1、chgrp&#xff1a;更改文件属组2、chown&#xff1a;更改文件属主&#xff0c;也可以同时更改文件属组3、chmod&#xff1a;更改文件9个属性————————如觉不错&#xff0c;随手点赞&#xff…

微信小程序真机调试连接状态一直在正常和未链接之间反复横跳?

背景&#xff1a;小程序真机调试的时候&#xff0c;发现真机的network不显示接口调用情况&#xff0c;控制台也没有输出内容。具体如下所示&#xff1b; 解决方法&#xff1a; 1、确保手机端连接的网络和微信开发者工具网络一致&#xff0c;比如用同一个WiFi 2、真机自动调试…

编程知识\_C与汇编深入分析

1. 汇编怎么调用C函数 1.1 直接调用 bl main 1.2 想传参数怎么办&#xff1f; 在arm中有个ATPCS规则(ARM-THUMB procedure call standard&#xff08;ARM-Thumb过程调用标准&#xff09;。 约定r0-r15寄存器的用途&#xff1a; r0-r3 调用者和被调用者之间传参数 r4-r11 函…

Flink SQL自定义标量函数(Scalar Function)

使用场景&#xff1a; 标量函数即 UDF&#xff0c;⽤于进⼀条数据出⼀条数据的场景。 开发流程&#xff1a; 实现 org.apache.flink.table.functions.ScalarFunction 接⼝实现⼀个或者多个⾃定义的 eval 函数&#xff0c;名称必须叫做 eval&#xff0c;eval ⽅法签名必须是 p…

冒泡排序

贵阳这个地方的天气变化好大呀&#xff0c;前两天晒大太阳&#xff0c;今天就冷的脚抖&#xff0c;简直不要太冷&#xff0c;但是不管怎么样&#xff0c;还是要学习的哟&#xff01; 冬天来了&#xff0c;春天确实还有一点远&#xff01; 好了&#xff0c;话不多说&#xff0c;…

springboot rocketmq 延时消息、延迟消息

rocketmq也有延迟消息&#xff0c;经典的应用场景&#xff1a;订单30分钟未支付&#xff0c;则取消的场景 其他博客提到从rocketmq5.0开始&#xff0c;支持自定义延迟时间&#xff0c;4.x只支持预定义延迟时间&#xff0c;安装rocketmq可参考RocketMq简介及安装、docker安装ro…

【C++】模板初阶

目录 一&#xff0c;泛型编程 二&#xff0c;函数模板 1&#xff0c;函数模板概念 2&#xff0c;函数模板格式 3&#xff0c;函数模板的原理 4&#xff0c;函数模板的实例化 5&#xff0c;模板参数的匹配原则 三&#xff0c;类模板 1&#xff0c;类模板的定义格式 2&…

⑤ 【MySQL】DCL语句 —— 用户管理、权限控制

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ MySQL用户与权限 ⑤ 【MySQL】DCL语句 —— 用…

pytorch中对nn.BatchNorm2d()函数的理解

pytorch中对BatchNorm2d函数的理解 简介计算3. Pytorch的nn.BatchNorm2d()函数4 代码示例 简介 机器学习中&#xff0c;进行模型训练之前&#xff0c;需对数据做归一化处理&#xff0c;使其分布一致。在深度神经网络训练过程中&#xff0c;通常一次训练是一个batch&#xff0c…

U-Mail邮件系统安全登录解决方案

企业邮箱是企业对内对外商务往来的主要通信工具&#xff0c;并且企业邮箱里面还包含了大量企业内部隐私信息、商业机密等&#xff0c;很容易成为黑客的攻击目标。其中邮件盗号是企业邮箱遭受攻击的主要形式&#xff0c;一旦企业邮箱密码被黑客盗取&#xff0c;黑客不仅可以利用…

操作系统 | 虚拟机及linux的安装

​ &#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《操作系统实验室》&#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 目录结构 1.操作系统实验之虚拟机及linux的安装 1.1 实验目的 1.2 实验内容 1.3 实验步骤 …

BIO、NIO、AIO之间有什么区别

文章目录 BIO优缺点示例代码 NIO优缺点示例代码 AIO优缺点示例代码 总结 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 BIO、NIO和AIO是Java编程语言中用于处理输入输出&#xff08;IO…

MYSQL字符串函数详解和实战(字符串函数大全,内含示例)

MySQL提供了许多字符串函数&#xff0c;用于处理和操作字符串数据。以下是一些常用的MYSQL字符串函数。 建议收藏以备后续用到查阅参考。 目录 一、CONCAT 拼接字符串 二、CONCAT_WS 拼接字符串 三、SUBSTR 取子字符串 四、SUBSTRING 取子字符串 五、SUBSTRING_INDEX 取子…

《红蓝攻防对抗实战》十二.内网穿透之利用ICMP协议进行隧道穿透

内网穿透之利用ICMP协议进行隧道穿透 一.前言二.前文推荐三.利用ICMP协议进行隧道穿透1.ICMPsh获取反弹shell2.PingTunnel 搭建隧道 四.本篇总结 一.前言 本文介绍了利用ICMP协议进行隧道穿透的方法。ICMP协议不需要开放端口&#xff0c;可以将TCP/UDP数据封装到ICMP的Ping数据…

Mysql数据库 14.SQL语言 视图

一、视图的概念 视图&#xff1a;就是由数据库中一张或多张表根据特定的条件查询出的数据狗造成的虚拟表 二、视图的作用 安全性&#xff0c;简单性 三、视图的语法 语法 create view 视图表 as select_statement; 代码实现 #创建视图 将查询结果创建称为视图&#x…

Flutter开发中的一些Tips(四)

最近接手了一个flutter项目&#xff0c;整体感觉代码质量不高&#xff0c;感觉有些是初学者容易犯的问题。几年前写的前三篇&#xff0c;我是站在我自己开发遇到问题的角度&#xff0c;这篇是站在别人遇到问题的角度&#xff0c;算是一种补充。下面我整理一下遇到的小问题&…

中国专利转让数据集(1985-2021年)

专利转让数据追踪和记录专利从一个实体转移到另一个实体的过程。这些数据不仅包括参与转让的申请人和受让人的身份信息&#xff0c;如名字和地址&#xff0c;还涵盖了转让的具体法律细节&#xff0c;包括转让执行日、转让次数、法律状态变更&#xff0c;以及转让登记的相关信息…

在Spring Boot中使用MyBatis访问数据库

MyBatis&#xff0c;这个对各位使用Java开发的开发者来说还是蛮重要的&#xff0c;我相信诸位在企业开发项目的时候&#xff0c;大多数采用的是Mybatis。使用MyBatis帮助我们解决各种问题&#xff0c;实际上这篇文章&#xff0c;基本上默认为可以跳过的一篇&#xff0c;但是为了…

Linux服务器从零开始训练 RT-DETR 改进项目 (Ultralytics) 教程,改进RTDETR算法(包括使用训练、验证、推理教程)

手把手从零开始训练 RT-DETR 改进项目 (Ultralytics版本) 教程,改进RTDETR算法 本文以Linux服务器为例:从零开始使用Linux训练 RT-DETR 算法项目 《芒果剑指 RT-DETR 目标检测算法 改进》 适用于芒果专栏改进RT-DETR算法 文章目录 百度 RT-DETR 算法介绍改进网络代码汇总第…

arcgis基础篇--实验

一、绘制带空洞的面要素 方法一&#xff1a;先绘制出一个面区域&#xff0c;然后在面上再绘制一个面区域代表面洞&#xff0c;两者位于同一个图层内&#xff0c;选中代表面洞的区域&#xff0c;选择【编辑器】-【裁剪】工具&#xff0c;将面裁剪出一个洞&#xff0c;随后删除代…