经过周六一天,周一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. javascript系列-class10.DOM(下)

    1.node节点(更详细的获取(设置)页面中所有的内容)         根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:   元素是节点的别称,节点包含元素当然节点还有 ...

  2. (转载)RecyclerView之ItemDecoration由浅入深

    RecyclerView之ItemDecoration由浅入深 作者 小武站台 关注 2016.09.19 18:20 字数 1155 阅读 10480评论 15喜欢 91赞赏 3 译文的GitHub ...

  3. 3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)

    3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称.它相当于是对每个数据块应用三次DES加密算法.由于计 ...

  4. C# 分隔字符串成为字符串数组的方法(保留分隔符)

    要求如下: source string: mmmmmmynameismickeym separator: m result string []: {"m", "m&quo ...

  5. 重设数据文件大小sql语句

    set verify off column file_name format a50 word_wrapped column smallest format 999,990 heading " ...

  6. Python学习---Day96

    转载:http://www.cnblogs.com/wupeiqi/articles/6229292.html Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可 ...

  7. You Probably Don’t Need a Message Queue

    原文地址 I’m a minimalist, and I don’t like to complicate software too early and unnecessarily. And addi ...

  8. 洛谷 P2279 [HNOI2003]消防局的设立 (树形dp or 贪心)

    一看到这道题就知道是树形dp 之前做过类似的题,只不过保护的范围是1 所以简单很多. 这道题保护的范围是2,就复杂了很多. 我就开始列状态,然后发现竟然有5种 然后我就开始列方程. 但是我考虑的时候是 ...

  9. 紫书 例题 10-1 UVa 11582 (unsigned long long+模)

    (1)这道题要用到 unsigned long long, 弄了我好久 这道题范围可以达到2的64次方-1, 而long long 最多到2的63次方-1, 而unsigned long long可以 ...

  10. 紫书 习题8-11 UVa 1615 (区间选点问题)

    这个点就是贪心策略中的区间选点问题. 把右端点从大到小排序, 左端点从小到大排序. 每次取区间右端点就可以了, 到不能覆盖的时候就ans++, 重新取点 ps:这道题不考虑精度也可以过 要着重复习一下 ...