【BZOJ3217】ALOEXT 分块
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3217
分块过掉辣!!!!!!$O(n^{1.5}+q\times \sqrt{n})$的分块过掉辣!!
而且速度贼快内存贼小啊(成功踩到b站第一)
由于此题需要强制在线的删除或者插入,所以我们基于块状链表分块,在每个块内存储指定区间内的所有数,以及该区间内的最大值和次大值,同时再维护一个由该区间内所有数组成的trie树。
对于修改一个数,首先在该块的trie数中删除该数(直接伪删),然后再插入,接着更新最大值和次大值。
对于插入一个数,直接在trie树中插入该数,随后在块状链表中插入,更新最大值和次大值。最后判断是否要将该块拆分(如果要察费直接暴力重构两个块即可)
对于删除一个数,trie树伪删除+块链删除+更新最大值和次大值。随后判断该块大小是否等于0(为零可以直接删掉这个块了)
对于查询最大值,首先查询出该区间内的次大值。对于完全包含的块,直接将该值丢到该块的trie树中求最大值,对于非完全包含的块,直接暴力求即可。
PS:经过测试,每个块的大小设置为3200最好(达到3200后切成两块1600的)。最初块大小为400,b站上跑了15.5s,把块大小改为3200后变成3.8s,直接rank1了。
UPD:前段时间被卡到第二,后来重新把块大小调整为2620,并且加上fread与fwrite,卡到3312ms,重回rank1。
(不知能否继续优化.....)
#include<bits/stdc++.h>
#define M 5000000
#define N 100
using namespace std;
struct trie{
int a[],sum;
}p[M]; int uset=;
int add(int now,int x,int px){
if(!now) now=++uset;
int ret=now;
for(int i=;i>=;i--){
bool k=x&(<<i); p[now].sum+=px;
if(p[now].a[k]) now=p[now].a[k];
else uset++,p[now].a[k]=uset,now=uset;
}
p[now].sum+=px;
return ret;
}
int getmax(int now,int x){
int ans=;
for(int i=;i>=;i--){
bool k=x&(<<i);
if(p[p[now].a[-k]].sum)
now=p[now].a[-k],ans+=(<<i);
else now=p[now].a[k];
}
return ans;
}
struct kuai{
int rt,use,next;
int max1,max2,a[N*+];
kuai(){
rt=use=next=max1=max2=;
memset(a,,sizeof(a));
}
void getmax(){
max1=max2=;
for(int i=;i<=use;i++)
if(a[i]>max1) max2=max1,max1=a[i];
else if(a[i]>max2) max2=a[i];
}
}a[N*]; int use=;
void updata(int id,int zhi){
for(int i=;i;i=a[i].next)
if(a[i].use>=id){
int last=a[i].a[id]; a[i].a[id]=zhi;
a[i].rt=add(a[i].rt,last,-);
add(a[i].rt,zhi,);
a[i].getmax();
return;
}else id-=a[i].use;
}
void cut(int i){
int j=++use;
a[i].use=a[j].use=N*;
a[j].next=a[i].next; a[i].next=j;
for(int k=;k<=N*;k++)
a[j].a[k]=a[i].a[k+N*],a[i].a[k+N*]=;
a[i].max1=a[i].max2=;
a[i].getmax(); a[j].getmax();
a[i].rt=add(,a[i].a[],);
a[j].rt=add(,a[j].a[],);
for(int k=;k<=N*;k++){
add(a[i].rt,a[i].a[k],);
add(a[j].rt,a[j].a[k],);
}
}
void insert(int x,int id){
int i,pre;
for(i=;i;pre=i,i=a[i].next)
if(a[i].use<id) id-=a[i].use;
else break;
if(!i) i=pre,id+=a[i].use;
for(int j=a[i].use;j>=id;j--) a[i].a[j+]=a[i].a[j];
a[i].a[id]=x; a[i].use++;
a[i].rt=add(a[i].rt,x,);
if(x>a[i].max1) a[i].max2=a[i].max1,a[i].max1=x;
else if(x>a[i].max2) a[i].max2=x;
if(a[i].use>=N*) cut(i);
}
void del(int id){
int i,pre=,x;
for(i=;i;pre=i,i=a[i].next)
if(a[i].use<id) id-=a[i].use;
else break;
x=a[i].a[id]; add(a[i].rt,x,-);
for(int j=id;j<=a[i].use;j++) a[i].a[j]=a[i].a[j+];
a[i].use--;
if(a[i].use==) {a[pre].next=a[i].next; return;}
if(a[i].max2>x) return;
a[i].getmax();
}
int getmax2(int l,int r){
int max1=,max2=,sum=;
int i,pre;
for(i=;i;pre=i,i=a[i].next){
if(l<=sum+&&sum+a[i].use<=r){
if(a[i].max1>max1) max2=max1,max1=a[i].max1;
else if(a[i].max1>max2) max2=a[i].max1;
if(a[i].max2>max2) max2=a[i].max2;
}
else if(sum+<=l&&r<=sum+a[i].use){
for(int j=l-sum;j<=r-sum;j++)
if(a[i].a[j]>max1) max2=max1,max1=a[i].a[j];
else if(a[i].a[j]>max2) max2=a[i].a[j];
}
else if(sum+<=l&&l<=sum+a[i].use){
for(int j=l-sum;j<=a[i].use;j++)
if(a[i].a[j]>max1) max2=max1,max1=a[i].a[j];
else if(a[i].a[j]>max2) max2=a[i].a[j];
}
else if(sum+<=r&&r<=sum+a[i].use){
for(int j=;j<=r-sum;j++)
if(a[i].a[j]>max1) max2=max1,max1=a[i].a[j];
else if(a[i].a[j]>max2) max2=a[i].a[j];
}
sum+=a[i].use;
}
return max2;
}
int query(int l,int r){
int x=getmax2(l,r),maxn=,sum=;
int i,pre;
for(i=;i;pre=i,i=a[i].next){
if(l<=sum+&&sum+a[i].use<=r){
maxn=max(maxn,getmax(a[i].rt,x));
}
else if(sum+<=l&&r<=sum+a[i].use){
for(int j=l-sum;j<=r-sum;j++)
maxn=max(maxn,x^a[i].a[j]);
}
else if(sum+<=l&&l<=sum+a[i].use){
for(int j=l-sum;j<=a[i].use;j++)
maxn=max(maxn,x^a[i].a[j]);
}
else if(sum+<=r&&r<=sum+a[i].use){
for(int j=;j<=r-sum;j++)
maxn=max(maxn,x^a[i].a[j]);
}
sum+=a[i].use;
}
return maxn;
}
int main(){
int n,m,lastans=,n0;
scanf("%d%d",&n,&m); n0=n;
for(int i=;i<=n;i++){
int x; scanf("%d",&x);
insert(x,i);
}
while(m--){
char c[]; int x,y;
scanf("%s%d",c,&x);
x=(x+lastans)%n0+;
if(c[]=='D'){del(x); n0--;continue;}
scanf("%d",&y);
if(c[]=='F') y=(y+lastans)%n0+;
else y=(y+lastans)%;
if(c[]=='I') insert(y,x),n0++;
if(c[]=='C') updata(x,y);
if(c[]=='F') printf("%d\n",lastans=query(min(x,y),max(x,y)));
}
}
【BZOJ3217】ALOEXT 分块的更多相关文章
- BZOJ3217 : ALOEXT
替罪羊树套Trie,Trie合并用线段树合并,注意常数优化. 顺便AC800题纪念~~~ #include<cstdio> #include<cmath> #include&l ...
- 【BZOJ3217】ALOEXT 替罪羊树+Trie树
[BZOJ3217]ALOEXT Description taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手. 突然有一天,taor ...
- 【bzoj3217】ALOEXT 替罪羊树套Trie树
题目描述 taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手. 突然有一天,taorunz来到了一个密室,里面放着一排可移动存储器, ...
- PHP搭建大文件切割分块上传功能
背景 在网站开发中,文件上传是很常见的一个功能.相信很多人都会遇到这种情况,想传一个文件上去,然后网页提示"该文件过大".因为一般情况下,我们都需要对上传的文件大小做限制,防止出现 ...
- POJ2104 K-th Number [分块做法]
传送:主席树做法http://www.cnblogs.com/candy99/p/6160704.html 做那倒带修改的主席树时就发现分块可以做,然后就试了试 思想和教主的魔法差不多,只不过那个是求 ...
- HDU 4467 分块
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4467 题意:给定n个点m条边的无向图,点被染色(黑0/白1),边带边权.然后q个询问.询问分为两种: ...
- 2016 ACM/ICPC Asia Regional Dalian Online 1010 Weak Pair dfs序+分块
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...
- CC countari & 分块+FFT
题意: 求一个序列中顺序的长度为3的等差数列. SOL: 对于这种计数问题都是用个数的卷积来进行统计.然而对于这个题有顺序的限制,不好直接统计,于是竟然可以分块?惊为天人... 考虑分块以后的序列: ...
- bzoj2002弹(dan)飞绵羊 分块水过
据说是道lct求深度的题 但是在小猫大的指点下用分块就n^1.5水过了 = =数据忘记加强系列 代码极其不美观,原因是一开始是听小猫大讲的题意,还以为是弹到最前面... #include <cs ...
随机推荐
- idea开发工具下报Set language level to 6-@Override in interfaces的解决方法
idea开发工具下报Set language level to 6-@Override in interfaces的解决方法 实现接口时报如下错误:Set language level to 6-@O ...
- 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)
传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...
- 2018.09.02 bzoj1025: [SCOI2009]游戏(计数dp+线筛预处理)
传送门 要将所有置换变成一个轮换,显然轮换的周期是所有置换长度的最小公倍数. 于是我们只需要求长度不超过n,且长度最小公倍数为t的不同置换数. 而我们知道,lcm只跟所有素数的最高位有关. 因此lcm ...
- Django入门与实践-第20章:QuerySets(查询结果集)(完结)
http://127.0.0.1:8000/boards/1/ #boards/models.py from django.utils.text import Truncator class Topi ...
- gj3 Python数据模型(魔法函数)
3.1 什么是魔法函数 类里面,实现某些特性的内置函数,类似 def __xx__(): 的形式. 不要自己定义XX,并不是和某个类挂钩的 class Company(object): def __i ...
- BZOJ 1003 物流运输 (dp + dijkstra)
1003: [ZJOI2006]物流运输 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8672 Solved: 3678[Submit][Stat ...
- ubuntu 14.04查看java的安装路径
有时候,使用apt-get install 安装了某个软件之后,却不知道这个软件的安装路径在哪里. 那怎么样去找出这个软件的安装路径呢? 下面我们java 这个软件为例, 找出ubuntu 14.04 ...
- (线段树)Balanced Lineup --POJ --3264
链接: 对于POJ老是爆,我也是醉了, 链接等等再发吧! http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82832#problem/G 只 ...
- gridview的编辑,更新,取消,自动分页等
gridview编辑列,把左下角的"自动生成字段"的复选框的勾去掉 添加boundfield(绑定列)将其datafield设置为productname,headertext设置为 ...
- 一致性哈希算法和Go语言实现
一致性哈希算法,当我第一次听到这个名字的时候,感觉特别高深.而它往往会和分布式系统相关,准确的说,是分布式缓存. 在Web服务中,缓存是介于数据库和服务端程序之间的一个东西.在网站的业务还不是很大的时 ...