BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)
题目大意:给你一个序列,多次询问,每次取出一段连续的子序列$[l,r]$,询问这段子序列的逆序对个数,强制在线
很熟悉的分块套路啊,和很多可持久化01Trie的题目类似,用分块预处理出贡献,而这道题是用可持久化线段树罢了
首先对序列分块,设块大小为$S$
再建出主席树,我们就能在$O(logn)$时间内查询某个点$i$与区间$[l,r]$内的点产生的逆序对数量
然后处理出点和整块之间的答案,设$f(i,j)$表示第$i$个点与第$j$块的开始/末尾这段区间内的点产生的逆序对数量。
再根据 点到块的答案 统计出 块到块的答案
对于每次询问,利用预处理出的东西$O(1)$搞出 整块到整块 的贡献,再暴力枚举边角+主席树查询搞出 边角到整块 和 边角到边角 的贡献。
然后就会被卡常
我们可以用树状数组搞出 边角到边角 的贡献,再用预处理的信息搞出 边角对整块 的贡献...
虽然每次查询的时间也是$O(logn)$不变,但非递归的树状数组确实能减少大量的常数 #喷血
分析一下时间复杂度,预处理+查询=O(n\frac{n}{S}logn+QSlogn),因为预处理是用主席树查询的所以比较慢..块要开大一些
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 50500
#define M1 120
#define ll long long
#define uint unsigned int
using namespace std; template <typename _T> void read(_T &ret)
{
ret=; _T fh=; char c=getchar();
while(c<''||c>''){ if(c=='-') fh=-; c=getchar(); }
while(c>=''&&c<=''){ ret=ret*+c-''; c=getchar(); }
ret=ret*fh;
} struct SEG{
int ls[N1*],rs[N1*],sz[N1*],root[N1],tot;
void pushup(int rt){ sz[rt]=sz[ls[rt]]+sz[rs[rt]]; }
void upd(int x,int l,int r,int rt1,int &rt2,int w)
{
if(!rt2||rt1==rt2){ rt2=++tot; ls[rt2]=ls[rt1]; rs[rt2]=rs[rt1]; sz[rt2]=sz[rt1]; }
if(l==r){ sz[rt2]+=w; return; }
int mid=(l+r)>>;
if(x<=mid) upd(x,l,mid,ls[rt1],ls[rt2],w);
else upd(x,mid+,r,rs[rt1],rs[rt2],w);
pushup(rt2);
}
int query(int L,int R,int l,int r,int rt1,int rt2)
{
if(L<=l&&r<=R) return sz[rt2]-sz[rt1];
int mid=(l+r)>>,ans=;
if(L<=mid) ans+=query(L,R,l,mid,ls[rt1],ls[rt2]);
if(R>mid) ans+=query(L,R,mid+,r,rs[rt1],rs[rt2]);
return ans;
}
}s; int n,m,sq,Q,de; struct BIT{
int sum[N1];
int upd(int x,int w)
{
int i;
for(i=x;i<=m;i+=(i&(-i)))
sum[i]+=w;
}
int query(int x)
{
if(!x) return ; int i,ans=;
for(i=x;i>;i-=(i&(-i)))
ans+=sum[i];
return ans;
}
}bit; int a[N1],b[N1],pie[N1],st[M1],ed[M1];
uint f[N1][M1],g[M1][M1]; int main()
{
int i,j,k,l,r,q,x,y,px,py; uint ans=;
scanf("%d",&n);
for(i=;i<=n;i++) read(a[i]), b[i]=a[i];
sort(b+,b+n+); m=unique(b+,b+n+)-(b+);
for(i=;i<=n;i++) a[i]=lower_bound(b+,b+m+,a[i])-b;
for(i=;i<=n;i++) s.upd(a[i],,m,s.root[i-],s.root[i],); sq=;
for(i=;i<=n;i++) pie[i]=(i-)/sq+, ed[pie[i]]=i;
for(i=;i<=pie[n];i++) st[i]=(i-)*sq+;
for(i=;i<=n;i++)
{
if(a[i]<m)
{
for(j=;j<pie[i];j++)
f[i][j]=s.query(a[i]+,m,,m,s.root[st[j]-],s.root[i-]);
f[i][]=s.query(a[i]+,m,,m,s.root[st[pie[i]]-],s.root[i-]);
}
if(a[i]>)
{
for(j=pie[i];j<=pie[n];j++)
{
f[i][j]=s.query(,a[i]-,,m,s.root[i],s.root[ed[j]]);
g[pie[i]][j]+=f[i][j];
}
}
}
for(j=;j<=pie[n];j++)
for(i=;i+j<=pie[n];i++)
g[i][i+j]+=g[i+][i+j]; scanf("%d",&Q);
for(q=;q<=Q;q++)
{
read(x); read(y); x^=ans; y^=ans; ans=; px=pie[x]; py=pie[y];
if(px!=py){
if(px+<=py-) ans=g[px+][py-];
for(i=x;i<=ed[px];i++) ans+=f[i][py-];
if(px+==py){
for(i=st[py];i<=y;i++) ans+=f[i][];
}else{
for(i=st[py];i<=y;i++) ans+=f[i][px+];
}
for(i=st[py];i<=y;i++) bit.upd(a[i],);
for(i=x;i<=ed[px];i++) if(a[i]>) ans+=bit.query(a[i]-);
for(i=st[py];i<=y;i++) bit.upd(a[i],-);
}else{
for(i=y;i>=x;i--)
{
if(a[i]>) ans+=bit.query(a[i]-);
bit.upd(a[i],);
}
for(i=x;i<=y;i++) bit.upd(a[i],-);
}
printf("%u\n",ans);
}
return ;
}
BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)的更多相关文章
- BZOJ 3744 Gty的妹子序列 (分块 + BIT)
3744: Gty的妹子序列 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1931 Solved: 570[Submit][Status][Dis ...
- BZOJ 3744: Gty的妹子序列 [分块]
传送门 题意:询问区间内逆序对数 感觉这种题都成套路题了 两个预处理$f[i][j]$块i到j的逆序对数,$s[i][j]$前i块$\le j$的有多少个 f我直接处理成到元素j,方便一点 用个树状数 ...
- BZOJ 3744 Gty的妹子序列 分块+树状数组
具体分析见 搬来大佬博客 时间复杂度 O(nnlogn)O(n\sqrt nlogn)O(nnlogn) CODE #include <cmath> #include <cctyp ...
- 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树
题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...
- BZOJ 3744 Gty的妹子序列 做法集结
我只会O(nnlogn)O(n\sqrt nlogn)O(nnlogn)的 . . . . 这是分块+树状数组+主席树的做法O(nnlogn)O(n\sqrt nlogn)O(nnlogn) 搬来 ...
- P1972 [SDOI2009]HH的项链[离线+树状数组/主席树/分块/模拟]
题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链 ...
- BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树
BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树 题意: 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i, ...
- zoj2112 树状数组+主席树 区间动第k大
Dynamic Rankings Time Limit: 10000MS Memory Limit: 32768KB 64bit IO Format: %lld & %llu Subm ...
- 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...
随机推荐
- maven install:install出现的错误提示
maven install:install出现的错误提示 [INFO] --- maven-install-plugin:2.4:install (default-cli) @ maven028 -- ...
- HDOJ题目3440 House Man(差分约束)
House Man Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- pcm数据生成wav文件
Qt由pcm数据生成wav文件 void AudioGrabber::saveWave(const QString &fileName, const QByteArray &raw, ...
- outlook创建收信规则,将收到的所有邮件,转发到qq邮箱,然后删除
因为outlook默认只有400M的空间. 使用企业邮箱的时候,很快就满了. 本来是打算在qq邮箱中,添加其他邮箱来收取的. http://service.mail.qq.com/cgi-bin/he ...
- Android Calendar的运用
import java.text.DateFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; impo ...
- Android和H5交互-基础篇
hybrid App开发也不是什么新鲜事了,其中native和h5之间的交互则是必不可少的.Android中是如何和H5交互的? 1.webView加载页面 我们都知道在Android中是通过webV ...
- linux端口号与PID的互相查询
最近用linux在玩Tomcat,启动的时候总是会报错(8080/8009/8005) 于是整理了一下网上零乱的查看PID和端口的命令,以备记录. 1.由端口号查询PID号 首先myeclipse报错 ...
- Java-MyBatis:MyBatis
ylbtech-Java-MyBatis:MyBatis 1.返回顶部 1. MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foun ...
- 使用pycharm进行简单的数据库管理
功能简介 pycharm自带了一个简单的数据库插件,可以比较方便的进行简单的数据库操作. 例如: 1.创建,修改和删除数据表,字段,索引,主键,外键等. 2.提供table editor来进行数据操作 ...
- 原生JS---5
原生js学习笔记5——BOM操作 什么是BOM BOM:Browser Object Model 是浏览器对象模型,浏览器对象模型提供了独立与内容的.可以与浏览器窗口进行互动的对象结构,BOM由多个对 ...