当前位置: 首页 > news >正文

BZOJ1901:Zju2112 Dynamic Rankings——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=1901

Description

给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1
],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改
变后的a继续回答上面的问题。

Input

第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。
分别表示序列的长度和指令的个数。
第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。
接下来的m行描述每条指令
每行的格式是下面两种格式中的一种。 
Q i j k 或者 C i t 
Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)
表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。
C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t
m,n≤10000

Output

 对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

Sample Input

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

Sample Output

3
6

————————————————————————————

UPT:18.4.2美化代码,删改题解。

带修改主席树板子题目(bzoj真喜欢权限板子题)

然后我学了一上午:https://www.cnblogs.com/candy99/p/6166467.html

总的来说如果我们暴力修改主席树的话,我们对于每一棵主席树都需要进行修改,那么这样时间复杂度就爆棚了。

而我们考虑,树状数组和线段树的修改仅仅只是logn的。

所以我们试着让树状数组套上主席树,这样就能方便的修改值了。

也就是说,树状数组的每一个节点都挂着一棵主席树,这样所需要修改的主席树就变成O(logn)棵了。

那么查询也很简单,就是树状数组的查询方法(因为我们外层包的是树状数组,所以查询就是在查主席树的根,也就不需要主席树了)。

显然空间复杂度为O(nlognlogn)

!但是!我学的那篇博客提供了一种O(2nlogn)的做法。

我们直接将修改操作另开一棵树状数组(upt:其实是开一个主席树然后用树状数组的lowbit修改)维护,这样就变成了两个主席树了,查询的时候两者的和一加即可。

注意事项:

1.注意区分两个主席树,本代码中rt为原序列主席树,root为存修改的主席树。

2.空间记得根据空间复杂度开。

3.不要用什么玄学的stl,不然AC变TLE就是一瞬间的事情。

4.离散化。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=20010;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct tree{
    int l,r,sum;
}tr[N*100];
struct question{
    char s[10];
    int i,j,k,t;
}q[N];
int a[N],b[N],rt[N],root[N],n,m,Q,pool;
int q1[N],t1,q2[N],t2;
inline void initLSH(){
    sort(b+1,b+m+1);
    m=unique(b+1,b+m+1)-b-1;
    return;
}
inline int LSH(int v){return lower_bound(b+1,b+m+1,v)-b;}
inline int lowbit(int x){return x&-x;}
inline void insert(int y,int &x,int l,int r,int p,int v){
    tr[x=++pool]=tr[y];
    tr[x].sum+=v;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(p<=mid)insert(tr[y].l,tr[x].l,l,mid,p,v);
    else insert(tr[y].r,tr[x].r,mid+1,r,p,v);
}
inline void add(int pos,int v){
    int p=LSH(a[pos]);
    for(int i=pos;i<=n;i+=lowbit(i))insert(root[i],root[i],1,m,p,v);
    //注意这里是root
}
inline int cal(){
    int sum1=0,sum2=0;
    for(int i=1;i<=t1;i++)sum1+=tr[tr[q1[i]].l].sum;
    for(int i=1;i<=t2;i++)sum2+=tr[tr[q2[i]].l].sum;
    return sum2-sum1;
}
inline int query(int nl,int nr,int k){
    int l=1,r=m;t1=t2=0;
    for(int i=nl;i;i-=lowbit(i))q1[++t1]=root[i];
    for(int i=nr;i;i-=lowbit(i))q2[++t2]=root[i];
    //注意这里是root
    nl=rt[nl],nr=rt[nr];
    //注意这里是rt
    while(l<r){
    int ls=cal()+tr[tr[nr].l].sum-tr[tr[nl].l].sum;
    int mid=(l+r)>>1;
    if(k<=ls){
        for(int i=1;i<=t1;i++)q1[i]=tr[q1[i]].l;
        for(int i=1;i<=t2;i++)q2[i]=tr[q2[i]].l;
        nl=tr[nl].l;nr=tr[nr].l;
        r=mid;
    }else{
        for(int i=1;i<=t1;i++)q1[i]=tr[q1[i]].r;
        for(int i=1;i<=t2;i++)q2[i]=tr[q2[i]].r;
        nl=tr[nl].r;nr=tr[nr].r;
        l=mid+1;k-=ls;
    }
    }
    return l;
}
int main(){
    n=read();
    Q=read();
    for(int i=1;i<=n;i++)a[i]=b[++m]=read();
    for(int i=1;i<=Q;i++){
    scanf("%s",q[i].s);
    if(q[i].s[0]=='Q'){
        q[i].i=read();q[i].j=read();q[i].k=read();
    }
    else{
        q[i].i=read();
        q[i].t=b[++m]=read();
    }
    }
    initLSH();
    for(int i=1;i<=n;i++)insert(rt[i-1],rt[i],1,m,LSH(a[i]),1);
    //注意这里是rt
    for(int i=1;i<=Q;i++){
    if(q[i].s[0]=='Q')
        printf("%d\n",b[query(q[i].i-1,q[i].j,q[i].k)]);
    else{
        add(q[i].i,-1);
        a[q[i].i]=q[i].t;
        add(q[i].i,1);
    }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/luyouqi233/p/8157534.html

相关文章:

  • Android交互
  • 第 15 章 Admonition 警告与提示
  • Android OkHttp简易使用
  • 怎么让div内容超出后自动显示滚动条
  • .NET使用存储过程实现对数据库的增删改查
  • extends继承
  • 《SqlServer 系列》 - 函数
  • Android 100+行实现本地跳一跳辅助(不需要连接电脑)
  • MyBatis DAO层传递参数到mapping.xml
  • 微内核与面向组件
  • 运维学python之爬虫中级篇(二)线程、协程
  • 资料推荐--Google Java编码规范
  • Python中的string模块的学习
  • bzoj千题计划205:bzoj3529: [Sdoi2014]数表
  • 关于多线程的参数问题
  • express.js的介绍及使用
  • git 常用命令
  • jdbc就是这么简单
  • mac修复ab及siege安装
  • PAT A1120
  • 测试如何在敏捷团队中工作?
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 基于游标的分页接口实现
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 如何设计一个微型分布式架构?
  • 十年未变!安全,谁之责?(下)
  • 责任链模式的两种实现
  • 怎么将电脑中的声音录制成WAV格式
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​linux启动进程的方式
  • ​渐进式Web应用PWA的未来
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • #includecmath
  • #大学#套接字
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (离散数学)逻辑连接词
  • (十)T检验-第一部分
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (四) 虚拟摄像头vivi体验
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .Net 应用中使用dot trace进行性能诊断
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • [20171102]视图v$session中process字段含义
  • [C++ 从入门到精通] 12.重载运算符、赋值运算符重载、析构函数
  • [Django 0-1] Core.Email 模块
  • [javaee基础] 常见的javaweb笔试选择题含答案
  • [LeetCode周赛复盘] 第 310 场周赛20220911
  • [Linux](16)网络编程:网络概述,网络基本原理,套接字,UDP,TCP,并发服务器编程,守护(精灵)进程
  • [Mybatis-Plus笔记] MybatisPlus-03-QueryWrapper条件构造器
  • [No000010F]Git8/9-使用GitHub