经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题.

Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
// 带插入区间 k 小值
// 外层:替罪羊
// 内层:权值线段树
using namespace std;
#define setIO(s) freopen(s".in","r",stdin), freopen(s".out","w",stdout)
#define debug() printf("OK\n")
#define maxn 11005000
#define N 70002
int n,lastans;
struct Segment_Tree{
struct Node{
int ls,rs,siz;
Node(int ls=0,int rs=0,int siz=0):ls(ls),rs(rs),siz(siz){}
}node[maxn];
queue<int>Q;
void init(){ for(int i=1;i<maxn;++i) Q.push(i); }
void newnode(int &o) { o=Q.front(), Q.pop(); }
void update(int l,int r,int &o,int pos,int delta){
if(!o) newnode(o);
node[o].siz+=delta;
if(!node[o].siz) { dfs(o); return; }
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) update(l,mid,node[o].ls,pos,delta);
else update(mid+1,r,node[o].rs,pos,delta);
}
void dfs(int &o){
if(!o)return;
dfs(node[o].ls),Q.push(o),dfs(node[o].rs);
node[o].siz=0;
o=0;
}
}segin;
struct Binary_Search_Tree{
inline bool check(int son,int o){
if(son*10>=o*9) return true;
return false;
}
int cnt,root;
int seq[N],count[3];
vector<int>re;
struct Node{
int ls,rs,siz,root,cur,val;
Node(int ls=0,int rs=0,int siz=0,int root=0,int cur=0,int val=0):ls(ls),rs(rs),root(root),cur(cur),val(val){}
}node[maxn];
inline void newnode(int &o,int val){ o=++cnt,node[o].val=val,node[o].siz=1; }
void dfs(int &o){
if(!o) return;
segin.dfs(node[o].root),segin.dfs(node[o].cur);
dfs(node[o].ls),re.push_back(o),dfs(node[o].rs);
node[o].siz=0;
o=0; }
void construct(int l,int r,int &o){
if(l>r)return;
int mid=(l+r)>>1;
o=re[mid]; for(int i=l;i<=r;++i)
segin.update(0,N,node[o].root,node[re[i]].val,1); segin.update(0,N,node[o].cur,node[o].val,1);
if(l==r){ node[o].siz=1; return; } construct(l,mid-1,node[o].ls), construct(mid+1,r,node[o].rs);
node[o].siz=node[node[o].ls].siz+node[node[o].rs].siz+1;
}
inline void Rebuild(int &o){ re.clear(),dfs(o),construct(0,re.size()-1,o); }
void insert(int &o,int k,int val,bool is){
if(!o){
newnode(o,val),segin.update(0,N,node[o].root,val,1),segin.update(0,N,node[o].cur,val,1);
return;
}
++node[o].siz, segin.update(0,N,node[o].root,val,1);
bool tag;
if(k<=node[node[o].ls].siz+1) tag=check(node[node[o].ls].siz+1,node[o].siz), insert(node[o].ls,k,val,is||tag);
else tag=check(node[node[o].rs].siz+1,node[o].siz), insert(node[o].rs,k-node[node[o].ls].siz-1,val,is||tag);
if(!is&&tag) Rebuild(o);
}
int modify(int o,int pos,int delta){
int num;
if(pos==node[node[o].ls].siz+1) {
segin.update(0,N,node[o].root,node[o].val,-1),segin.dfs(node[o].cur),node[o].cur=0;
segin.update(0,N,node[o].root,delta,1),segin.update(0,N,node[o].cur,delta,1);
num=node[o].val,node[o].val=delta;
return num;
}
if(pos<=node[node[o].ls].siz) num=modify(node[o].ls,pos,delta);
else num=modify(node[o].rs,pos-node[node[o].ls].siz-1,delta);
segin.update(0,N,node[o].root,num,-1),segin.update(0,N,node[o].root,delta,1);
return num;
}
void Build(){
scanf("%d",&n),re.clear();
int tmp,x ;
for(int i=1;i<=n;++i)
scanf("%d",&tmp),newnode(x,tmp),re.push_back(x);
construct(0,re.size()-1,root);
}
void Get(int l,int r,int o,int L,int R){
if(l>R||r<L||l>r||!o)return;
if(l>=L&&r<=R) { seq[++count[0]]=node[o].root; return; }
int mid=node[node[o].ls].siz+l;
if(mid>=L&&mid<=R&&mid<=r) seq[++count[0]]=node[o].cur;
Get(l,mid-1,node[o].ls,L,R),Get(mid+1,r,node[o].rs,L,R);
}
int solve(int l,int r,int k){
if(l==r) return l;
int lsum=0;
for(int i=1;i<=count[0];++i) {
lsum+=segin.node[segin.node[seq[i]].ls].siz;
}
int mid=(l+r)>>1;
if(k>lsum)
{
for(int i=1;i<=count[0];++i) seq[i]=segin.node[seq[i]].rs;
return solve(mid+1,r,k-lsum);
}
else
{
for(int i=1;i<=count[0];++i)seq[i]=segin.node[seq[i]].ls;
return solve(l,mid,k);
}
}
void Insert(){
int a,b;
++n,scanf("%d%d",&a,&b),a^=lastans,b^=lastans,insert(root,a,b,0);
}
void Modify(){
int a,b;
scanf("%d%d",&a,&b),a^=lastans,b^=lastans,modify(root,a,b);
}
int Query(){
int L,R,k;
count[0]=0, scanf("%d%d%d",&L,&R,&k),L^=lastans,R^=lastans,k^=lastans;
if(L>R)swap(L,R);
Get(1,n,root,L,R);
return solve(0,N,k);
}
}BST;
int main(){
//setIO("input");
segin.init(), BST.Build();
char opt[10];
int q;
scanf("%d",&q);
while(q--){
scanf("%s",opt);
if(opt[0]=='I') BST.Insert();
if(opt[0]=='M') BST.Modify();
if(opt[0]=='Q') printf("%d\n",lastans=BST.Query());
}
return 0;
}

  

3065: 带插入区间K小值_树套树_替罪羊树_权值线段树的更多相关文章

  1. bzoj 3065: 带插入区间K小值 替罪羊树 && AC300

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1062  Solved: 253[Submit][Status] Des ...

  2. 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树

    题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...

  3. BZOJ 3065 带插入区间K小值(sag套线段树)

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 4696  Solved: 1527[Submit][Status][Di ...

  4. 【BZOJ】3065: 带插入区间K小值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...

  5. bzoj 3065: 带插入区间K小值(分块)

    Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它 ...

  6. BZOJ 3065 带插入区间K小值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3065 思路:替罪羊树套权值线段树. 当替罪羊树某个子树大于某个比利(比例)时就暴力重构,本题时间复杂 ...

  7. BZOJ 3065 带插入区间K小值 (替罪羊树套线段树)

    毒瘤题.参考抄自博客:hzwer 第一次写替罪羊树,完全是照着题解写的,发现这玩意儿好强啊,不用旋转每次都重构还能nlognnlognnlogn. 还有外面二分和里面线段树的值域一样,那么r = mi ...

  8. 【学习笔记】浅析平衡树套线段树 & 带插入区间K小值

    常见的树套树 一般来说,在嵌套数据结构中,线段树多被作为外层结构使用. 但线段树毕竟是 静态 的结构,导致了一些不便. 下面是一个难以维护的例子: 带插入区间 \(k\) 小值问题 来源:Luogu ...

  9. [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树

    刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...

随机推荐

  1. 【linux】——centos 分辨率配置

    用过centos的朋友肯定知道centos在默认安装的时候显示器的分辨率只有800*600,但是我们想把改成1024*768或者更大,怎么办呢,我也是试过了才知道,首先打开系统-管理-显示-硬件-显示 ...

  2. [NOI.AC 2018NOIP模拟赛 第三场 ] 染色 解题报告 (DP)

    题目链接:http://noi.ac/contest/12/problem/37 题目: 小W收到了一张纸带,纸带上有 n个位置.现在他想把这个纸带染色,他一共有 m 种颜色,每个位置都可以染任意颜色 ...

  3. xBIM 实战03 使用WPF技术实现IFC模型的加载与浏览

    系列目录    [已更新最新开发文章,点击查看详细]  WPF应用程序在底层使用 DirectX ,无论设计复杂的3D图形(这是 DirectX 的特长所在)还是绘制简单的按钮与文本,所有绘图工作都是 ...

  4. Pyinstaller 0

    Pyinstaller 是一个小的可以打包我们所写的Python脚本,来生成相应的可执行文件. 它是怎么工作的? PyInstaller读取您编写的Python脚本.它会分析您的代码,以发现您的脚本执 ...

  5. 压缩图片C#算法

    转载自 http://www.open-open.com/lib/view/open1391348644910.html using System.IO; using System.Drawing; ...

  6. 优动漫PAINT基础系列之存储格式说明

    本篇经验带大家了解优动漫PAINT可以存储成哪些格式! 最近有收到试用优动漫PAINT个人版试用版的小伙伴提问,优动漫PAINT可以导出什么格式文件呢?今天就这一问题做一下解答〜 优动漫PAINT[试 ...

  7. canvas图片滚动

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  8. [ZJOI2015]幻想乡战略游戏(点分树)

    题意自己看... 思路 没想到今(昨)天刷着刷着点分治的水题,就刷出来了一个点分树... 然后就疯狂地找题解,代码,最后终于把它给弄懂了. 点分树——动态点分治,对于此题来说,我们设u为当前的补给站位 ...

  9. dropload上拉加载 下拉刷新

    1.引入css.js <link rel="stylesheet" href=" ${pageContext.request.contextPath}/dist/d ...

  10. Linux学习02--Linux一切皆文件

    Linux学习第二部 Linux一切皆对象 啊啊啊啊啊,今天被学妹说太直了,嘤嘤嘤. 学习linux两三天了,前期感觉并不难,只是命令多,多记记多敲一敲就能都记住了.希望自己能够坚持下去吧! 下面是根 ...