BZOJ3196: Tyvj 1730 二逼平衡树

传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3196

题意:

1.查询k在区间内的排名

2.查询区间内排名为k的值

3.修改某一位值上的数值

4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)

5.查询k在区间内的后继(后继定义为大于x,且最小的数)

树套树模板题,在TLE的边缘疯狂试探

/**************************************************************
    Problem: 3196
    User: buerdepepeqi
    Language: C++
    Result: Accepted
    Time:9660 ms
    Memory:73172 kb
****************************************************************/
 
#include<iostream>
#include<cstdlib>
#include<cstdio>
#define inf 100000000
#define N 200001
#define M 3000001
using namespace std;
int n,m,sz,tmp,a[N];
int ls[M],rs[M],rnd[M],v[M],s[M],w[M];
int root[N];
void update(int k)
{s[k]=s[ls[k]]+s[rs[k]]+w[k];}
void rturn(int &k)
{int t=ls[k];ls[k]=rs[t];rs[t]=k;s[t]=s[k];update(k);k=t;}
void lturn(int &k)
{int t=rs[k];rs[k]=ls[t];ls[t]=k;s[t]=s[k];update(k);k=t;}
void insert(int &k,int num)
{
    if(!k){k=++sz;s[k]=w[k]=1;v[k]=num;rnd[k]=rand();return;}
    s[k]++;
    if(num==v[k])w[k]++;
    else if(num<v[k]){insert(ls[k],num);if(rnd[ls[k]]<rnd[k])rturn(k);}
    else {insert(rs[k],num);if(rnd[rs[k]]<rnd[k])lturn(k);}
}
void del(int &k,int num)
{
    if(v[k]==num)
    {
        if(w[k]>1){w[k]--;s[k]--;return;}
        if(ls[k]*rs[k]==0)k=ls[k]+rs[k];
        else if(rnd[ls[k]]<rnd[rs[k]]){rturn(k);del(k,num);}
        else {lturn(k);del(k,num);}
    }
    else if(num<v[k])
       {del(ls[k],num);s[k]--;}
    else {del(rs[k],num);s[k]--;}
}
void build(int k,int l,int r,int x,int num)
{
    insert(root[k],num);
    if(l==r)return;
    int mid=(l+r)>>1;
    if(x<=mid)build(k<<1,l,mid,x,num);
    else build(k<<1|1,mid+1,r,x,num);
}
void ask_rank(int k,int num)
{
    if(!k)return;
    if(num==v[k]){tmp+=s[ls[k]];return;}
    else if(num<v[k])ask_rank(ls[k],num);
    else {tmp+=s[ls[k]]+w[k];ask_rank(rs[k],num);}
}
void get_rank(int k,int l,int r,int x,int y,int num)
{
    if(l==x&&r==y){ask_rank(root[k],num);return;}
    int mid=(l+r)>>1;
    if(mid>=y)get_rank(k<<1,l,mid,x,y,num);
    else if(mid<x)get_rank(k<<1|1,mid+1,r,x,y,num);
    else
    {
        get_rank(k<<1,l,mid,x,mid,num);
        get_rank(k<<1|1,mid+1,r,mid+1,y,num);
    }
}
void get_index(int x,int y,int z)
{
    int l=0,r=inf,ans;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        tmp=1;get_rank(1,1,n,x,y,mid);
        if(tmp<=z){l=mid+1;ans=mid;}
        else r=mid-1;
        }
    printf("%d\n",ans);
}
void change(int k,int l,int r,int x,int num,int y)
{
    del(root[k],y);
    insert(root[k],num);
    if(l==r)return;
    int mid=(l+r)>>1;
    if(x<=mid)change(k<<1,l,mid,x,num,y);
    else change(k<<1|1,mid+1,r,x,num,y);
}
void before(int k,int num)
{
    if(!k)return;
    if(v[k]<num){tmp=max(v[k],tmp);before(rs[k],num);}
    else before(ls[k],num);
}
void after(int k,int num)
{
    if(!k)return;
    if(v[k]>num){tmp=min(v[k],tmp);after(ls[k],num);}
    else after(rs[k],num);
}
void ask_after(int k,int l,int r,int x,int y,int num)
{
    if(l==x&&r==y){after(root[k],num);return;}
    int mid=(l+r)>>1;
    if(mid>=y)ask_after(k<<1,l,mid,x,y,num);
    else if(mid<x)ask_after(k<<1|1,mid+1,r,x,y,num);
    else
    {
        ask_after(k<<1,l,mid,x,mid,num);
        ask_after(k<<1|1,mid+1,r,mid+1,y,num);
    }
}
void ask_before(int k,int l,int r,int x,int y,int num)
{
    if(l==x&&r==y){before(root[k],num);return;}
    int mid=(l+r)>>1;
    if(mid>=y)ask_before(k<<1,l,mid,x,y,num);
    else if(mid<x)ask_before(k<<1|1,mid+1,r,x,y,num);
    else
    {
        ask_before(k<<1,l,mid,x,mid,num);
        ask_before(k<<1|1,mid+1,r,mid+1,y,num);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)build(1,1,n,i,a[i]);
    for(int i=1;i<=m;i++)
    {
        int f;scanf("%d",&f);
        int x,y,k;
        switch(f)
        {
            case 1:scanf("%d%d%d",&x,&y,&k);tmp=1;get_rank(1,1,n,x,y,k);printf("%d\n",tmp);break;
            case 2:scanf("%d%d%d",&x,&y,&k);get_index(x,y,k);break;
            case 3:scanf("%d%d",&x,&y);change(1,1,n,x,y,a[x]);a[x]=y;break;
            case 4:scanf("%d%d%d",&x,&y,&k);tmp=0;ask_before(1,1,n,x,y,k);printf("%d\n",tmp);break;
            case 5:scanf("%d%d%d",&x,&y,&k);tmp=inf;ask_after(1,1,n,x,y,k);printf("%d\n",tmp);break;
         }
    }
    return 0;
}

BZOJ 3166的更多相关文章

  1. bzoj 3166 [Heoi2013]Alo 可持久化Trie

    3166: [Heoi2013]Alo Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1227  Solved: 569[Submit][Status ...

  2. BZOJ 3166: [Heoi2013]Alo

    3166: [Heoi2013]Alo Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 923  Solved: 437[Submit][Status] ...

  3. BZOJ 3166 HEOI2013 ALO 可持久化trie+st表

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3166(洛谷上也有) 题意概述: 给出一个序列,对于一个区间,其权值为区间中的次大值亦或区 ...

  4. 【BZOJ 3166】【HEOI 2013】Alo

    http://www.lydsy.com/JudgeOnline/problem.php?id=3166 这道题难点在于求能对一个次大值有贡献的区间. 设这个次大值为\(a_i\),\(a_i\)左边 ...

  5. Bzoj 3166 [Heoi2013] Alo 题解

    3166: [Heoi2013]Alo Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1118  Solved: 518[Submit][Status ...

  6. BZOJ 3166 Alo

    处理出每个数最靠近它的左右两个比它大的数. 然后可持久化trie. #include<iostream> #include<cstdio> #include<cstrin ...

  7. bzoj 3166 可持久化Tire

    每一个数能做出的贡献就是其两端第二个比他大的中间的数和他的异或值 按权值大小排序,按照位置扔进set,set内的元素都是比他大的,也是全的 然后Tire上跑就行了.. #include<cstd ...

  8. BZOJ - 3166 可持久化Trie 维护次大区间

    题意:给出\(a[1...n]\),找出一个连续区间\(a[l...r],r>l\),令该区间的次大值为\(a_k\),使得\(a_k⊕a_i,l≤i≤r\)最大,输出全局最优解 (这题意有点别 ...

  9. BZOJ 3166 set+可持久化trie树(OR 莫队)

    思路: 1.找次大值 我们不妨设当前点是次大的 那这段区间为 左边第二个比它大的点的坐标+1 和右边第二个比它大的点的坐标-1 2.用可持久化trie树找异或最大值 也可以用莫队 //By Siriu ...

  10. BZOJ 3166 [HEOI2013]Alo (可持久化01Trie+链表)

    题目大意:给你一个长度为$n$的序列,让你找出一段子序列,求其中的 次大值 异或 序列里一个数 能得到的最大值 先对序列建出可持久化$Trie$ 按元素的值从小到大遍历,设当前元素的位置是i,找出它左 ...

随机推荐

  1. day20 BBS前奏

    Django的ORM操作 1.FK 2.M2M 3.O2O 4.CURD 5.aggregate聚合 6.F 7.Q FORM表单 Django form model form views介绍 adm ...

  2. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线 学习目标 了解几个用以表达真实场景的标志和2D图像 ...

  3. C++之ARX,Acstring,ACahr转char

    AcDbText* pText = AcDbText::cast(pEnt); AcString sText = DBHelper::AcStringFree(pText->textString ...

  4. BZOJ 1834网络扩容题解

    一道不算太难的题目 但是真的很恶心 显然,对于第一问,我们直接无脑打模板就好了 第二问也不是很难,我们将每条边再连一条容量为inf,费用为w的边 但是流量只要小于第一问的答案加k就行了 所以我们增加一 ...

  5. 干货 | 解读MySQL 8.0新特性:Skip Scan Range

    MySQL从8.0.13版本开始支持一种新的range scan方式,称为Loose Skip Scan.该特性由Facebook贡献.我们知道在之前的版本中,如果要使用到索引进行扫描,条件必须满足索 ...

  6. 2017 ACM-ICPC 亚洲区(西安赛区)网络赛: B. Coin 【概率题】【数论】

    Bob has a not even coin(就是一个不均匀的硬币,朝上的概率不一定是1/2), every time he tosses the coin, the probability tha ...

  7. Centos7.3-mysql5.7复制安装过程

    一.环境 192.168.56.102 为主服务器 192.168.56.101 为从服务器 Mysql5.7.20 二进制安装包环境 1. 下载免编译安装包并进行安装 从官网下载 mysql-5.7 ...

  8. Java练习 SDUT-3422_小金问呀问不会问题

    小金问呀问不会问题 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 众所周知,C语言的学习是我们程序设计基础的重点和主要 ...

  9. hdu 2473 Junk-Mail Filter (暴力并查集)

    Problem - 2473 为什么标题写的是暴力并查集?因为我的解法跟网上的有所不同,方法暴力很多. 先解释题意,这是一个模拟处理垃圾邮件的问题.垃圾邮件要根据它们的性质进行分类.对于10w个邮件, ...

  10. github下载慢,轻松提速教程

    获取github的IP地址访问:https://www.ipaddress.com/ 网址 依次获取以下三个网址的IP github.comgithub.global.ssl.fastly.netco ...