【函数式权值分块】【分块】bzoj1901 Zju2112 Dynamic Rankings
论某O(n*sqrt(n))的带修改区间k大值算法。
首先对序列分块,分成sqrt(n)块。
然后对权值分块,共维护sqrt(n)个权值分块,对于权值分块T[i],存储了序列分块的前i块的权值情况。
对于区间询问,需要获得区间中每个值出现的次数,然后按权值扫O(sqrt(n)),完整的部分我们可以通过权值分块差分(O(1))得到(比如Lb~Rb块就是T[Rb]-T[Lb-1]),零散的部分我们再维护一个额外的权值分块,累计上该值即可。O(sqrt(n))。
对于修改,直接在该位置之后的所有权值分块里修改,单次修改O(1),涉及O(sqrt(n))个权值分块,所以是O(sqrt(n))的。
所以平均每次操作是O(sqrt(n))的,空间复杂度是O(n*sqrt(n))的。
(缺陷:①必须离散化;②空间复杂度较高,对n=100000,几乎会卡空间)
这份代码目前在 bzoj 上 Rank1
| No. | RunID | User | Memory | Time | Language | Code_Length | Submit_Time |
| 1 | 802901(8) | lizitong | 10192 KB | 208 MS | C++ | 3468 B | 2014-12-11 13:01:16 |
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int Num,CH[12],f,c;
inline void R(int &x){
c=0;f=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0');
x*=f;
}
inline void P(int x){
if(x<10)putchar(x+'0');
else{P(x/10);putchar(x%10+'0');}
}
struct Point{int v,p;}t[20001];
bool operator < (const Point &a,const Point &b){return a.v<b.v;}
int n,m,xs[10001],ys[10001],ks[10001],sum=1,en,en2,ma[20001],l[111],r[111];
int a[20001],num[10001],num2[20001],l2[145];
char op[10001];
struct Val_Block
{
int b[20001],sumv[145];
void Insert(const int &x){++b[x]; ++sumv[num2[x]];}
void Delete(const int &x){--b[x]; --sumv[num2[x]];}
}T[111],S;
int Kth(const int &L,const int &R,const int &x)
{
int cnt=0,res;
if(num[L]+1>=num[R])
{
for(int i=L;i<=R;++i) S.Insert(a[i]);
for(int i=1;;++i)
{
cnt+=S.sumv[i];
if(cnt>=x)
{
cnt-=S.sumv[i];
for(int j=l2[i];;++j)
{cnt+=S.b[j]; if(cnt>=x) {res=j; goto OUT2;}}
}
} OUT2:
for(int i=L;i<=R;++i) S.Delete(a[i]);
return res;
}
for(int i=L;i<=r[num[L]];++i) S.Insert(a[i]);
for(int i=l[num[R]];i<=R;++i) S.Insert(a[i]);
int LB=num[L],RB=num[R]-1;
for(int i=1;;++i)
{
cnt+=(T[RB].sumv[i]-T[LB].sumv[i]+S.sumv[i]);
if(cnt>=x)
{
cnt-=(T[RB].sumv[i]-T[LB].sumv[i]+S.sumv[i]);
for(int j=l2[i];;++j)
{cnt+=(T[RB].b[j]-T[LB].b[j]+S.b[j]); if(cnt>=x) {res=j; goto OUT;}}
}
} OUT:
for(int i=L;i<=r[num[L]];++i) S.Delete(a[i]);
for(int i=l[num[R]];i<=R;++i) S.Delete(a[i]);
return res;
}
void makeblock()
{
int sz=sqrt(n); if(!sz) sz=1;
for(;sum*sz<n;++sum)
{
l[sum]=r[sum-1]+1; r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
}
l[sum]=r[sum-1]+1; r[sum]=n;
for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
}
void val_mb()
{
int tot=1,sz=sqrt(en2); if(!sz) sz=1;
for(;tot*sz<en2;++tot)
{
l2[tot]=(tot-1)*sz+1;
int R=tot*sz;
for(int i=l2[tot];i<=R;++i) num2[i]=tot;
}
l2[tot]=(tot-1)*sz+1;
for(int i=l2[tot];i<=en2;++i) num2[i]=tot;
}
void Init_Ts()
{
for(int i=1;i<=sum;++i)
{
T[i]=T[i-1];
for(int j=l[i];j<=r[i];++j) T[i].Insert(a[j]);
}
}
int main()
{
R(n); R(m); en=n; makeblock();
for(int i=1;i<=n;++i) {R(t[i].v); t[i].p=i;} getchar();
for(int i=1;i<=m;++i)
{
op[i]=getchar(); R(xs[i]); R(ys[i]);
if(op[i]=='Q') R(ks[i]);
else {t[++en].v=ys[i]; t[en].p=en;}
}
sort(t+1,t+en+1);
ma[a[t[1].p]=++en2]=t[1].v;
for(int i=2;i<=en;++i)
{
if(t[i].v!=t[i-1].v) ++en2;
ma[a[t[i].p]=en2]=t[i].v;
}
val_mb(); Init_Ts(); en=n;
for(int i=1;i<=m;++i)
{
if(op[i]=='C')
{
++en;
for(int j=num[xs[i]];j<=sum;++j)
T[j].Delete(a[xs[i]]),T[j].Insert(a[en]);
a[xs[i]]=a[en];
}
else P(ma[Kth(xs[i],ys[i],ks[i])]),puts("");
}
return 0;
}
【函数式权值分块】【分块】bzoj1901 Zju2112 Dynamic Rankings的更多相关文章
- 【分块】bzoj1901 Zju2112 Dynamic Rankings
区间k大,分块大法好,每个区间内存储一个有序表. 二分答案,统计在区间内小于二分到的答案的值的个数,在每个整块内二分.零散的暴力即可. 还是说∵有二分操作,∴每个块的大小定为sqrt(n*log2(n ...
- [BZOJ1901]Zju2112 Dynamic Rankings
[BZOJ1901]Zju2112 Dynamic Rankings 试题描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i ...
- BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Submit: 6058 Solved: 2521 [Su ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
- [luogu2617][bzoj1901][Zju2112]Dynamic Rankings【树套树+树状数组+主席树】
题目网址 [传送门] 题目大意 请你设计一个数据结构,支持单点修改,区间查询排名k. 感想(以下省略脏话inf个字) 真的强力吹爆洛谷数据,一般的树套树还给我T了一般的点,加强的待修主席树还给我卡了几 ...
- BZOJ1901 Zju2112 Dynamic Rankings 【树状数组套主席树】
题目 给定一个含有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- ...
- 【基数排序】bzoj1901 Zju2112 Dynamic Rankings
论NOIP级别的n²算法…… 跟分块比起来,理论上十万的数据只慢4.5倍左右的样子…… #include<cstdio> #include<algorithm> using n ...
- BZOJ1901 Zju2112 Dynamic Rankings 主席树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1901 题意概括 给你一段序列(n个数),让你支持一些操作(共m次), 有两种操作,一种是询问区间第 ...
- BZOJ1901: Zju2112 Dynamic Rankings(整体二分 树状数组)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9094 Solved: 3808[Submit][Status][Discuss] Descript ...
随机推荐
- OpenJudge百炼-2747-数字方格-C语言-枚举
描述:如上图,有3个方格,每个方格里面都有一个整数a1,a2,a3.已知0 <= a1, a2, a3 <= n,而且a1 + a2是2的倍数,a2 + a3是3的倍数, a1 + a2 ...
- Codeforces Round #523 (Div. 2) A. Coins
A. Coins 题目链接:https://codeforc.es/contest/1061/problem/A 题意: 给出n和s,要在1-n中选数(可重复),问最少选多少数可以使其和为s. 题解: ...
- ACM模板~求第k短路 ~~~A*+Dijkstra
#include <map> #include <set> #include <cmath> #include <ctime> #include < ...
- 工作总结-js插件
因最近工作需要,使用了一些js插件,感觉还不错,记录下来以便以后使用. 1.图片轮播插件: 扩展:梦想天空系列:http://www.cnblogs.com/lhb25/archive/2013/01 ...
- Install Rancher server
1.pre-requirement: sudo nmtui # sudo hostnamectl set-hostname <hostname> $ sudo hostnamectl se ...
- Spring学习--使用 utility scheme 定义集合及 p命名空间
util schema 定义集合: 使用基本的集合标签定义集合时 , 不能将集合作为独立的 Bean 定义 , 导致其他 Bean 无法引用该集合 , 所以无法在不同 Bean 之间共享集合. 可以用 ...
- python最简单发送邮件
#!/usr/bin/env python #coding:utf8 #Author:lsp #Date:下午5:51:13 #Version:0.1 #Function: #导入smtplib和MI ...
- 调用webservice接口
这里是cxf服务器,采用myeclipse6.5,把wsdl放到本地的方式. 新建一个包, 把解析到的类放在这个包下面. 生成的代码结构: 调用: public static String callI ...
- L2-002. 链表去重---模拟
https://www.patest.cn/contests/gplt/L2-002 L2-002. 链表去重 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 ...
- 动态规划:数位DP
数位dp一般应用于: 求出在给定区间[A,B]内,符合条件P(i)的数i的个数 条件P(i)一般与数的大小无关,而与 数的组成 有关 例题是一道BZOJ1833,让求出区间所有整数每个数字出现的次数 ...