【BZOJ3600】没有人的算术 - 替罪羊树+线段树
题意:
题解:
Orz vfleaking……真·神题
做法大概是先把题意中定义的“数”都赋一个实数权值,用平衡树来维护整个从大到小排序过的序列,再用线段树查询最值;
这样做为什么是对的?考虑插入一个数$x$,我们已经知道了$x_L$和$x_R$在序列中的位置,就可以直接每次$O(1)$比较权值大小来找到$x$应该插入的位置,这样子单次插入是$O(logn)$的;
再考虑赋值,可以把根节点的区间设为$(0,1)$,然后每个点的权值都赋为这个区间中点的值,向子树递归赋值即可;由于平衡树树高是$O(logn)$的,最小精度限制就是$2^{-logn}=\frac{1}{n}$的,可以直接用double存;但是一个问题是普通的平衡树在旋转之后整棵子树的权值都需要重新计算,因此就要用不需要旋转的重量平衡树,这里我用的替罪羊树;
ps:貌似我写的替罪羊是假的……rebuild的地方会重复rec很多次……alpha小了会T,大了会WA……经过面对oj调参+玄学读优才卡时限过……
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 1000000007
#define eps 1e-9
using namespace std;
typedef long long ll;
typedef double db;
const db alpha=0.865;
int n,m,l,r,k,rt=,cur,cnt=,top=,nw[],st[];
db s[];
char op[];
struct num{
int x,y;
num(){}
num(int _x,int _y){
x=_x,y=_y;
}
friend bool operator ==(num a,num b){
return a.x==b.x&&a.y==b.y;
}
friend bool operator <(num a,num b){
return a.x==b.x?s[a.y]<s[b.y]:s[a.x]<s[b.x];
}
};
struct node{
int ls,rs,siz;
//db s;
num v;
}t[];
struct _node{
int v,p;
}tr[];
char buffer[],*hd,*tl;
inline char Getchar(){
if(hd==tl){
int len=fread(buffer,,,stdin);
hd=buffer,tl=hd+len;
if(hd==tl)
return EOF;
}
return *hd++;
}
inline int rd(){
register int x=,f=;
char c;
do{
c=Getchar();
if(c=='-')f=-;
}while(!isdigit(c));
do{
x=(x<<)+(x<<)+(c^);
c=Getchar();
}while(isdigit(c));
return x*f;
}
void getmx(num &a,num b){
if((a.y==b.y&&a.x>b.x)||s[a.y]<s[b.y])a=b;
}
bool ndrb(int u){
return t[t[u].ls].siz>t[u].siz*alpha+||t[t[u].rs].siz>t[u].siz*alpha+;
}
void rec(int u){
if(t[u].ls)rec(t[u].ls);
st[++top]=u;
if(t[u].rs)rec(t[u].rs);
}
void rebuild(int &u,int l,int r,db L,db R){
int mid=(l+r)/;
db Mid=(L+R)/;
u=st[mid];
s[u]=Mid;
t[u].ls=t[u].rs=;
if(l<mid)rebuild(t[u].ls,l,mid-,L,Mid);
if(mid<r)rebuild(t[u].rs,mid+,r,Mid,R);
t[u].siz=t[t[u].ls].siz+t[t[u].rs].siz;
}
void rb(int &u,db L,db R){
top=;
rec(u);
rebuild(u,,top,L,R);
}
int ins(int &u,db L,db R,num x){
db Mid=(L+R)/;
if(!u){
u=++cnt;
t[u].v=x;
s[u]=Mid;
t[u].ls=t[u].rs=;
t[u].siz=;
return u;
}
t[u].siz++;
if(ndrb(u))rb(u,L,R);
if(x==t[u].v)return u;
else if(x<t[u].v)return ins(t[u].ls,L,Mid,x);
else return ins(t[u].rs,Mid,R,x);
}
void pushup(int u){
if(tr[u*].v==tr[u*+].v||s[tr[u*].v]>s[tr[u*+].v]){
tr[u].v=tr[u*].v;
tr[u].p=tr[u*].p;
}else{
tr[u].v=tr[u*+].v;
tr[u].p=tr[u*+].p;
}
}
void build(int l,int r,int u){
tr[u].v=;
tr[u].p=l;
if(l==r)return;
int mid=(l+r)/;
build(l,mid,u*);
build(mid+,r,u*+);
}
void updata(int l,int r,int u,int p){
if(l==r){
tr[u].v=nw[l];
tr[u].p=l;
return;
}
int mid=(l+r)/;
if(p<=mid)updata(l,mid,u*,p);
else updata(mid+,r,u*+,p);
pushup(u);
}
num query(int l,int r,int u,int L,int R){
if(L<=l&&r<=R){
return num(tr[u].p,tr[u].v);
}
int mid=(l+r)/;
num ret(,);
if(L<=mid)getmx(ret,query(l,mid,u*,L,R));
if(mid<R)getmx(ret,query(mid+,r,u*+,L,R));
return ret;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("10.in","r",stdin);
freopen("my.out","w",stdout);
#endif
//scanf("%d%d",&n,&m);
n=rd(),m=rd();
cur=ins(rt,,,num(,));
for(int i=;i<=n;i++)nw[i]=cur;
build(,n,);
for(int i=;i<=m;i++){
//scanf("%s%d%d",op,&l,&r);
char ch;
ch=Getchar();
while(ch!='C'&&ch!='Q')ch=Getchar();
l=rd(),r=rd();
if(ch=='C'){
//scanf("%d",&k);
k=rd();
nw[k]=ins(rt,,,num(nw[l],nw[r]));
updata(,n,,k);
}else printf("%d\n",query(,n,,l,r).x);
}
return ;
}
【BZOJ3600】没有人的算术 - 替罪羊树+线段树的更多相关文章
- 「BZOJ3065」带插入区间第K小值 替罪羊树×线段树
题目描述 从前有\(n\)只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力\(a_i\).跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间\(k\)小值.他 ...
- 浅谈树套树(线段树套平衡树)&学习笔记
0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...
- 「BZOJ3600」没有人的算术 替罪羊树+线段树
题目描述 过长--不想发图也不想发文字,所以就发链接吧-- 没有人的算术 题解 \(orz\)神题一枚 我们考虑如果插入的数不是数对,而是普通的数,这就是一道傻题了--直接线段树一顿乱上就可以了. 于 ...
- 【BZOJ3600】没有人的算术(替罪羊树+线段树)
点此看题面 大致题意: 定义任意数对\(>0\),数对之间比大小先比第一位.后比第二位,一开始数列全为\(0\),要求你支持\(a_k=(a_x,a_y)\)和询问区间最大值所在位置两种操作. ...
- bzoj 3600 没有人的算术 - 替罪羊树 - 线段树
题目都是图片,就不给了,就给链接好了 由于bzoj比较慢,就先给[vjudge传送门] 有兴趣的可以去逛bzoj[bzoj传送门] 题目大意 有n个数a[1],a[2],...,a[n],它们开始都是 ...
- 【题解】BZOJ 3600: 没有人的算术——替罪羊树、线段树
题目传送门 题意 具体的自己去上面看吧...反正不是权限题. 简单来说,就是定义了一类新的数,每个数是0或者为 \((x_L, x_R)\) ,同时定义比较大小的方式为:非零数大于零,否则按字典序比较 ...
- [BZOJ3600] 没有人的算术 [重量平衡树+权值线段树]
题面 传送门 思路 这道题目是陈立杰论文<重量平衡树和后缀平衡树在信息学奥赛中的应用 >中关于重量平衡树维护序列排名算法的一个应用 具体方法为:令根节点保存一个实数区间$[0,1]$ 若当 ...
- bzoj3600: 没有人的算术
题意:太难说了..手动去看吧反正不是权限题. 膜拜VFK大爷的神题! 其实一开始思路挺清楚的,如果我们能做到用一个实数去代表"数",这就是裸的动态区间最值查询. 关键是怎么用实数去 ...
- Codeforces 1045A Last chance 网络流,线段树,线段树优化建图
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045A.html 题目传送们 - CF1045A 题意 你有 $n$ 个炮,有 $m$ 个敌人,敌人排成一 ...
随机推荐
- 小记——Grub Rescue恢复
下面我要讲的是一个悲伤的故事 引子 电脑状况简介:两块硬盘(1HHD.1SSD),SSD上装了LINUX(40G)+WIN10(50G)的双系统,SSD剩余部分在WIN下使用装程序,HHD做仓库.LI ...
- js面向对象 多种创建对象方法小结
转自js面向对象 多种创建对象方法小结 1.对象字面量 var clock={ hour:12, minute:10, second:10, showTime:function(){ alert(th ...
- [Python] Create a minimal website in Python using the Flask Microframework
How to install Flask Use Flask to create a minimal website Build routes in Flask to respond to websi ...
- 【待解决】An internal error occurred during: "Launching baiduTest1". java.lang.NullPointerException
编写的一个Java类,以junit运行可以正常执行,以testNG执行就报如下错误 解决方法:
- 关联查询之map的延伸使用方法
<select id="front.sort.selectListall" parameterType="myshop.services.front.sort.be ...
- 0x58 数据结构优化DP
补写一下 poj3171 设f[i]表示覆盖L~i的最小花费,把区间按左端点排序,枚举区间,f[a[i].r]=min{f[a[i].l~(a[top].r-1)]}+a[i].c (当然还要和原值比 ...
- Quartz实例:quartz定时任务代码示例
转自:http://www.blogchong.com/post/96.html quartz定时任务调度框架,使用实例. Job类://即实际调度任务实现 . package net.csdn.ed ...
- [ASPX] 模版引擎XTemplate与代码生成器XCoder(源码)
模版引擎XTemplate是一个仿T4设计的引擎,功能上基本与T4一致(模版语法上完全兼容T4,模版头指令部分兼容). 自己设计模版引擎,就是为了代码生成器.网站模版.邮件模版等多种场合,也就是要能拿 ...
- 使用 `ConfigMap` 挂载配置文件
使用 ConfigMap 挂载配置文件 Intro 有一些敏感信息比如数据库连接字符串之类的出于安全考虑,这些敏感信息保存在了 Azure KeyVault 中,最近应用上了 k8s 部署,所以想把 ...
- Citrix架构
本图为citrix在Azure上的基本架构 包含了netscaler, VDA, DDC, AD四台服务器以及Azure SQL服务