题意:

题解:

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】没有人的算术 - 替罪羊树+线段树的更多相关文章

  1. 「BZOJ3065」带插入区间第K小值 替罪羊树×线段树

    题目描述 从前有\(n\)只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力\(a_i\).跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间\(k\)小值.他 ...

  2. 浅谈树套树(线段树套平衡树)&学习笔记

    0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...

  3. 「BZOJ3600」没有人的算术 替罪羊树+线段树

    题目描述 过长--不想发图也不想发文字,所以就发链接吧-- 没有人的算术 题解 \(orz\)神题一枚 我们考虑如果插入的数不是数对,而是普通的数,这就是一道傻题了--直接线段树一顿乱上就可以了. 于 ...

  4. 【BZOJ3600】没有人的算术(替罪羊树+线段树)

    点此看题面 大致题意: 定义任意数对\(>0\),数对之间比大小先比第一位.后比第二位,一开始数列全为\(0\),要求你支持\(a_k=(a_x,a_y)\)和询问区间最大值所在位置两种操作. ...

  5. bzoj 3600 没有人的算术 - 替罪羊树 - 线段树

    题目都是图片,就不给了,就给链接好了 由于bzoj比较慢,就先给[vjudge传送门] 有兴趣的可以去逛bzoj[bzoj传送门] 题目大意 有n个数a[1],a[2],...,a[n],它们开始都是 ...

  6. 【题解】BZOJ 3600: 没有人的算术——替罪羊树、线段树

    题目传送门 题意 具体的自己去上面看吧...反正不是权限题. 简单来说,就是定义了一类新的数,每个数是0或者为 \((x_L, x_R)\) ,同时定义比较大小的方式为:非零数大于零,否则按字典序比较 ...

  7. [BZOJ3600] 没有人的算术 [重量平衡树+权值线段树]

    题面 传送门 思路 这道题目是陈立杰论文<重量平衡树和后缀平衡树在信息学奥赛中的应用 >中关于重量平衡树维护序列排名算法的一个应用 具体方法为:令根节点保存一个实数区间$[0,1]$ 若当 ...

  8. bzoj3600: 没有人的算术

    题意:太难说了..手动去看吧反正不是权限题. 膜拜VFK大爷的神题! 其实一开始思路挺清楚的,如果我们能做到用一个实数去代表"数",这就是裸的动态区间最值查询. 关键是怎么用实数去 ...

  9. Codeforces 1045A Last chance 网络流,线段树,线段树优化建图

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045A.html 题目传送们 - CF1045A 题意 你有 $n$ 个炮,有 $m$ 个敌人,敌人排成一 ...

随机推荐

  1. [bzoj1316]树上的询问_点分治

    树上的询问 bzoj-1316 题目大意:一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No. 注释:$1\le n\le 10^4$,$1\ ...

  2. vue-自定义组件传

    项目中,我们经常会遇到自定义组件传值的问题,方法很多种,但是原理很简单,下述文档总结实际项目中使用的传值方式. 父组件传递给子组件某一值,子组件内会修改该值,然后父组件需要获取新值 ​ 在 Vue 中 ...

  3. POJ 2029

    二维树状数组可解此题 #include <iostream> #include <cstdio> #include <cstring> #include <a ...

  4. js为字符串编码

    js 提供了两组函数来进行字符串的编码与解码:escape()与unescape(). decodeURI()与encodeURI(); JavaScript escape() 函数 定义和使用方法 ...

  5. [Angular] Advanced DI

    In this post, we are going to see how to solve one design pattern challenge. The challenge is what w ...

  6. Android 5.0 怎样正确启用isLoggable(二)__原理分析

    前置文章 <Android 5.0 怎样正确启用isLoggable(一)__使用具体解释> 概要 在上文<Android 5.0 怎样正确启用isLoggable(一)__使用具体 ...

  7. Java设计模式之从[星际争霸的兵种升级]分析观察者(Observer)模式

    观察者模式定义对象的一种一对多的依赖关系.当一个对象的状态发生改变时.全部依赖于它的对象都会得到通知并被自己主动更新. 一个简单的样例是.在星际争霸的虫族中有一个0基础单位叫做跳狗(Zergling) ...

  8. PHP独立操作符

    & 与 ^ 位逻辑异或 $ # ! 逻辑或 ~  按位取反

  9. ssh 结构

    service:业务层 dao:数据訪问层 hibernate:持久层

  10. Adding Search

    https://docs.asp.net/en/latest/tutorials/first-mvc-app/search.html In this section you’ll add search ...