题意:太难说了。。手动去看吧反正不是权限题。

膜拜VFK大爷的神题!

其实一开始思路挺清楚的,如果我们能做到用一个实数去代表“数”,这就是裸的动态区间最值查询。

关键是怎么用实数去表示。如果我们单纯的把两个数进行O(1)运算去得到一个实数,这样很轻松就会被卡掉,因为无论是longlong还是double都是有限度的。怎么做呢?

这里有一个技巧:我们维护一个重量平衡树,每个节点管辖一个区间,这个区间的中位数为这个点的权值,而它的左儿子管辖左半边,右儿子管辖右半边。

问题来了,这不是差不多吗?并不是这样。因为我们会重构,树高有保证,所以我们肯定能表示出每一个数,而且还是绰绰有余。

重量平衡树可以用不旋转的treap或替罪羊树。

(吐槽一句,第一次写替罪羊树,真的好TM难写啊还套了个线段树而且我常数大的飞起,写了一整天)

 #include<bits/stdc++.h>
using namespace std;
#define N 500005
#define LL long long
inline LL read(){
LL x=,f=; char a=getchar();
while(a<'' || a>'') {if(a=='-') f=-; a=getchar();}
while(a>='' && a<='') x=x*+a-'',a=getchar();
return x*f;
}
int n,m; char st[];
LL MX;
#define SGT Scapegoat_Tree
#define ST Segment_Tree namespace Scapegoat_Tree{
#define eps 1e-12
const double alpha=0.75;
int ltst,wh,size=,tmp[N],root=,anew;
struct sgt{
LL l,r,mid; int fir,sec;
int son[],sz;
}tr[N];
inline int dcmp(int x,int y){
if(fabs((double)tr[x].sz*alpha-(double)tr[y].sz)<eps) return ;
else return (double)tr[x].sz*alpha>(double)tr[y].sz?:-;
}
inline void update(int x){
tr[x].sz=tr[tr[x].son[]].sz+tr[tr[x].son[]].sz+;
}
inline bool balance(int x){
return dcmp(x,tr[x].son[])>= && dcmp(x,tr[x].son[])>=;
}
void travel(int x){
if(!x) return;
travel(tr[x].son[]);
tmp[++tmp[]]=x;
travel(tr[x].son[]);
}
void rebuild(int &x,int l,int r,LL L,LL R){
if(l>r) {x=; return;}
int mid=(l+r)>>;
LL M=(L+R)/;
x=tmp[mid]; tr[x].l=L; tr[x].r=R; tr[x].mid=M;
if(l==r) {tr[x].sz=; tr[x].son[]=; tr[x].son[]=; return;}
rebuild(tr[x].son[],l,mid-,L,M); rebuild(tr[x].son[],mid+,r,M,R);
update(x);
}
void insert(int& x,LL L,LL R,int fir,int sec){
if(!x) {x=++size; anew=x;tr[x]=(sgt){L,R,(L+R)/,fir,sec,,,}; return;}
if(tr[tr[x].fir].mid==tr[fir].mid && tr[tr[x].sec].mid==tr[sec].mid) {anew=x; return;}
else if(tr[tr[x].fir].mid==tr[fir].mid){
if(tr[tr[x].sec].mid>tr[sec].mid) insert(tr[x].son[],tr[x].l,tr[x].mid,fir,sec);
else insert(tr[x].son[],tr[x].mid,tr[x].r,fir,sec);
}
else{
if(tr[tr[x].fir].mid>tr[fir].mid) insert(tr[x].son[],tr[x].l,tr[x].mid,fir,sec);
else insert(tr[x].son[],tr[x].mid,tr[x].r,fir,sec);
}
update(x);
if(tr[x].son[] && !balance(tr[x].son[])) ltst=x,wh=;
else if(tr[x].son[] && !balance(tr[x].son[])) ltst=x,wh=;
if(x==root && !balance(x)) tmp[]=,travel(root),rebuild(root,,tmp[],,MX);
}
}
namespace Segment_Tree{
int a[N];
struct seg{
int l,r,son[],mx_pos,num;
}tr[N];
inline void update(int x){
if(SGT::tr[tr[tr[tr[x].son[]].mx_pos].num].mid==SGT::tr[tr[tr[tr[x].son[]].mx_pos].num].mid){
int le=tr[tr[x].son[]].mx_pos,ri=tr[tr[x].son[]].mx_pos;
tr[x].mx_pos=tr[le].l<tr[ri].l?le:ri;
}
else if(SGT::tr[tr[tr[tr[x].son[]].mx_pos].num].mid>SGT::tr[tr[tr[tr[x].son[]].mx_pos].num].mid)
tr[x].mx_pos=tr[tr[x].son[]].mx_pos;
else tr[x].mx_pos=tr[tr[x].son[]].mx_pos;
}
void build(int x,int l,int r){
if(l==r) {tr[x]=(seg){l,r,,,x,};return;}
int mid=(l+r)>>; tr[x].l=l; tr[x].r=r;
tr[x].son[]=x<<; build(tr[x].son[],l,mid);
tr[x].son[]=x<<|; build(tr[x].son[],mid+,r);
update(x);
}
void modify(int x,int ai,int v){
int l=tr[x].l,r=tr[x].r;
if(l==r) {tr[x].num=v; return;}
int mid=(l+r)>>;
if(ai<=mid) modify(tr[x].son[],ai,v);
else modify(tr[x].son[],ai,v);
update(x);
}
int query(int x,int L,int R){
int l=tr[x].l,r=tr[x].r;
if(l==L && r==R) return tr[x].mx_pos;
int mid=(l+r)>>;
if(R<=mid) return query(tr[x].son[],L,R);
else if(mid<L) return query(tr[x].son[],L,R);
else{
int le=query(tr[x].son[],L,mid),ri=query(tr[x].son[],mid+,R);
if(SGT::tr[tr[le].num].mid==SGT::tr[tr[ri].num].mid) return tr[le].l<tr[ri].l?le:ri;
return SGT::tr[tr[le].num].mid>SGT::tr[tr[ri].num].mid?le:ri;
}
}
} int main(){
n=read(); m=read(); MX=;
for(int i=;i<=;i++) MX*=;
ST::build(,,n); SGT::tr[]=(SGT::sgt){,MX,(+MX)/,,,,,};
for(int i=;i<=n;i++) ST::a[i]=;
while(m--){
scanf("%s",st); int k,l=read(),r=read();
if(st[]=='C'){
k=read();
l=ST::a[l]; r=ST::a[r]; SGT::ltst=; SGT::insert(SGT::root,,MX,l,r);
if(SGT::ltst) {
SGT::tmp[]=; SGT::travel(SGT::tr[SGT::ltst].son[SGT::wh]);
LL L=SGT::tr[SGT::tr[SGT::ltst].son[SGT::wh]].l,R=SGT::tr[SGT::tr[SGT::ltst].son[SGT::wh]].r;
SGT::rebuild(SGT::tr[SGT::ltst].son[SGT::wh],,SGT::tmp[],L,R);
}
ST::modify(,k,SGT::anew),ST::a[k]=SGT::anew;
}else{
int ans=ST::query(,l,r);
ans=ST::tr[ans].l;
printf("%d\n",ans);
}
}
return ;
}

bzoj3600: 没有人的算术的更多相关文章

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

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

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

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

  3. BZOJ3600:没有人的算术

    传送门 如果能给每个 \(pair\) 按照权值编号就好了 假设之前已经有了所有的权值的编号,现在考虑编号新的 \(pair\) 如果看过了陈立杰的论文的话,不难得到一个重量平衡树的做法 给树上每个子 ...

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

    题意: 题解: Orz vfleaking……真·神题 做法大概是先把题意中定义的“数”都赋一个实数权值,用平衡树来维护整个从大到小排序过的序列,再用线段树查询最值: 这样做为什么是对的?考虑插入一个 ...

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

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

  6. bzoj 3600 没有人的算术——二叉查找树动态标号

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3600 已知 l 和 r 的排名,想快速知道 k 的排名.那么建一个 BIT ,用已知的排名做 ...

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

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

  8. bzoj 3600: 没有人的算术

    Description Solution 我们可以给每一个数钦定一个权值 , 这样就可以 \(O(1)\) 比较大小了. 考虑怎么确定权值: 用平衡树来维护 , 我们假设根节点管辖 \([1,2^{6 ...

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

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

随机推荐

  1. 使用MegaCli工具查看Raid磁盘阵列状态

    转载自:http://home.51.com/chenjianghui1987/diary/item/10051836.html 文章本身我不做过多修改了,在这里我就把自己在安装时候碰到的难点跟大家提 ...

  2. 【转】如何查看当前Open的Cursor

    遇到错误:A cursor with thename ' ' already exists,想要看是什么代码导致的.找到下面几种方法. --测试声明Cursor并且打开 DECLARE vend_cu ...

  3. docker设置并运行部分命令及原文

    1.设置开机启动 If you want Docker to start at boot, you should also: $ sudo systemctl enable docker 2. 启动, ...

  4. 源码剖析——深入Windows句柄本质

    参考资料: 1. http://www.codeforge.cn/read/146318/WinDef.h__html windef.h头文件 2. http://www.codeforge.cn/r ...

  5. 22.mongodb副本集集群

    软件版本64位:     $ wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.2.0.tgz     mongo ...

  6. 远程执行shellcode

    #include "Windows.h" #include <WinSock2.h> #include <stdio.h> #pragma comment( ...

  7. 删除文件夹工具【fuckwinfsdel】,如 node_modules

    强力删除文件夹. 安装 npm install fuckwinfsdel -g 使用 fuckwinfsdel youdir 例 fuckwinfsdel node_modules 项目地址 http ...

  8. UGUI text image 等加Shadow OutLine等

    Text,文本控件,同NGUI中的Label.支持动态字库.大小调节.富文本(基本的html标签格式)等等.描边.阴影等需要Effect组件支持.Add Component-->UI--> ...

  9. java:同步和死锁

    多个线程共享一个资源的时候需要进行同步(否则会出现错误:如负数,重复数),但是过多的同步会造成死锁. synchronized(this) { } 非同步情况: public class SyncTh ...

  10. java, mybatis, 调用mysql存储过程

    Map<String, Object> bindinfo = new HashMap<String, Object>();            bindinfo.put(&q ...