题意:

题解:

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. 关于Bubblesort算法

    Java中的经典算法之冒泡排序(Bubble Sort) 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2 ...

  2. 洛谷 P1692 部落卫队

    P1692 部落卫队 题目描述 原始部落byteland中的居民们为了争夺有限的资源,经常发生冲突.几乎每个居民都有他的仇敌.部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入伍, ...

  3. Spring Boot上传文件

    我们使用Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0. <parent> <groupId>org.springframework.boot& ...

  4. logistic regression model

    logistic regression model LR softmax classification Fly logistic regression model loss fuction softm ...

  5. 跟我学Java多线程——线程池与堵塞队列

    前言 上一篇文章中我们将ThreadPoolExecutor进行了深入的学习和介绍,实际上我们在项目中应用的时候非常少有直接应用ThreadPoolExecutor来创建线程池的.在jdk的api中有 ...

  6. win7/WIN8.1(x64) 下使用MSDE WIN10不行

    通过强制安装(使用管理员权限),手工启动服务的方式,能够在其win7 win81上安装并使用MSDE Microsoft SQL Server 2000 Service Pack 4 Desktop ...

  7. 实战c++中的string系列--CDuiString和string的转换(duilib中的cduistring)

    使用所duilib的人定会知道cduistring类型,先看看这个类是怎么定义的: class UILIB_API CDuiString { public: enum { MAX_LOCAL_STRI ...

  8. MySQL数据库表的数据插入、修改、删除、查询操作及实例应用

    一.MySQL数据库表的数据插入.修改.删除和查询 CREATE DATABASE db0504; USE db0504; CREATE TABLE student ( sno ) NOT NULL ...

  9. poj--1664--放苹果(递归好体)

    放苹果 Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %I64d & %I64u Submit Status De ...

  10. Quartz实例:quartz定时任务代码示例

    转自:http://www.blogchong.com/post/96.html quartz定时任务调度框架,使用实例. Job类://即实际调度任务实现 . package net.csdn.ed ...