题目分析:

首先这种乱七八糟的题目就分块。然后考虑逆序对的统计。

一是块内的,二是块之间的,三是一个块内一个块外,四是都在块外。

令分块大小为$S$。

块内的容易维护,单次维护时间是$O(S)$。

块之间的有两种维护方法,一种是在块内维持有序,那么修改的时候进行一次插排,查询的时候枚举每一块,然后二分查找;另一种是利用下面所述的另一个数组来做块内统计。第一种方法的时间是$O(S+\frac{n}{S}\log S)$;第二种是$O(\frac{n}{S}logn)$.这里我们需要用树状数组维护,但是树状数组带的$\log$与查找是独立的。

一个在块内一个在块外的通过枚举块外的,然后利用数组$f[i][j]$记录$1 \sim i$块小于等于$j$的数的个数,这里用树状数组维护前缀和。时间复杂度是$O(S \log n)$.

最后一部分单独提取出来求逆序对,时间$O(SlogS)$.

那么$O(Slogn) = O(\frac{n}{S}logn)$可以解得$S = O(\sqrt{n})$.

所以这样做的时间复杂度是$O(n\sqrt{n}logn)$

代码:

 #include<bits/stdc++.h>
using namespace std; const int srt = ;
const int maxn = ; int n,m;
int c[srt+][maxn],inside[maxn],con[srt+][srt+];
int a[maxn],ord[maxn]; int lowbit(int x){return x&-x;} void add(int now,int dr,int om){while(now <= n)c[om][now]+=dr,now+=lowbit(now);}
int query(int now,int om){
int ans = ;
while(now){ans += c[om][now]; now -= lowbit(now);}
return ans;
}
void Add(int now,int dr,int om){while(now<=n/srt+){con[om][now]+=dr;now += lowbit(now);}}
int Query(int now,int om){
int ans = ;
while(now){ans += con[om][now]; now -= lowbit(now);}
return ans;
} void read(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&m);
} void init(){
for(int i=,cnt=;i<=n;i+=srt,cnt++){
memset(c[],,sizeof(c[]));
for(int j=srt-;j>=;j--){
if(j+i > n) continue;
inside[cnt] += query(a[i+j]-,);
add(a[i+j],,);
}
}
for(int i=;(i-)*srt+<=n;i++){
memset(c[],,sizeof(c[]));
for(int j=(i-)*srt+;j<=min(n,i*srt);j++) add(a[j],,);
for(int j=i+;(j-)*srt+<=n;j++){
for(int k=(j-)*srt+;k<=min(n,j*srt);k++)
con[i][j] += query(n,)-query(a[k],);
}
}
for(int i=;(i-)*srt+<=n;i++){
int j; for(j=i+;(j-)*srt+<=n;j++);
for(;j>i;j--){ int z = con[i][j]; con[i][j] = ; Add(j,z,i); }
for(int j=(i-)*srt+;j<=min(n,i*srt);j++){
for(int k=i;(k-)*srt+<=n;k++) add(a[j],,k);
}
}
} void work(){
int lastans = ;memset(c[],,sizeof(c[]));
for(int i=;i<=m;i++){
int pv; scanf("%d",&pv);
if(pv == ){
int l,r; scanf("%d%d",&l,&r); l^=lastans; r^=lastans;
if(r-l < srt){
int ans = ;
for(int j=r;j>=l;j--){ans += query(a[j]-,);add(a[j],,);}
for(int j=r;j>=l;j--){add(a[j],-,);}
printf("%d\n",ans);lastans = ans;
continue;
}
int st=,ed=;
while((st-)*srt+ < l)st++; while(ed*srt<=r)ed++;ed--;
int ans = ; for(int j=st;j<=ed;j++)ans += inside[j];
for(int j=st;j<=ed;j++){ans += Query(ed,j);}
for(int j=l;j%srt!=;j++)ans+=query(a[j]-,ed)-query(a[j]-,st-);
for(int j=ed*srt+;j<=r;j++){
ans += (query(n,ed)-query(n,st-));
ans -= (query(a[j],ed)-query(a[j],st-));
}
for(int j=r;j>ed*srt;j--){ans += query(a[j]-,); add(a[j],,);}
for(int j=(st-)*srt;j>=l;j--){ans+=query(a[j]-,);add(a[j],,);}
for(int j=r;j>ed*srt;j--) add(a[j],-,);
for(int j=(st-)*srt;j>=l;j--) add(a[j],-,);
printf("%d\n",ans);lastans = ans;
}else{
int p,v; scanf("%d%d",&p,&v);p^=lastans,v ^= lastans;
int bel = p/srt+(p%srt!=);
for(int j=(bel-)*srt+;j<p;j++){
if(a[j] > a[p]) inside[bel]--; if(a[j] > v) inside[bel]++;
}
for(int j=p+;j<=bel*srt;j++){
if(a[j] < a[p]) inside[bel]--; if(a[j] < v) inside[bel]++;
}
for(int j=;j<bel;j++){
int z = (srt-query(a[p],j)+query(a[p],j-));
int zz = (srt-query(v,j)+query(v,j-));
Add(bel,zz-z,j);
}
for(int j=bel+;(j-)*srt+<=n;j++){
int z=query(a[p]-,j)-query(a[p]-,j-);
int r=query(v-,j)-query(v-,j-);
Add(j,r-z,bel);
}
for(int j=bel;(j-)*srt+<=n;j++){add(a[p],-,j); add(v,,j);}
a[p] = v;
}
}
} int main(){
read();
init();
work();
return ;
}

BZOJ3787 gty的文艺妹子序列 【树状数组】【分块】的更多相关文章

  1. BZOJ3787:Gty的文艺妹子序列(分块,树状数组)

    Description Autumn终于会求区间逆序对了!Bakser神犇决定再考验一下他,他说道: “在Gty的妹子序列里,某个妹子的美丽度可也是会变化的呢.你还能求出某个区间中妹子们美丽度的逆序对 ...

  2. BZOJ3787 : Gty的文艺妹子序列

    将序列分成$\sqrt{n}$块,预处理出每两块之间的逆序对数,以及ap[i]表示前i块内数字出现次数的树状数组 预处理:$O(n\sqrt{n}\log n)$ 修改时,ap[i]可以在$O(\sq ...

  3. 【分块】【树状数组】bzoj3787 Gty的文艺妹子序列

    题解懒得自己写了,Orz一发wangxz神犇的: http://bakser.gitcafe.com/2014/12/04/bzoj3787-Gty%E7%9A%84%E6%96%87%E8%89%B ...

  4. BZOJ 3787: Gty的文艺妹子序列

    3787: Gty的文艺妹子序列 Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 186  Solved: 58[Submit][Status][Dis ...

  5. BZOJ_2141_排队_树状数组+分块

    BZOJ2141_排队_树状数组+分块 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了 ...

  6. 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分

    题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...

  7. bzoj4553 [Tjoi2016&Heoi2016]序列 树状数组(区间最大值)+cqd

    [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1006  Solved: 464[Submit][ ...

  8. Wannafly Winter Camp 2020 Day 7A 序列 - 树状数组

    给定一个全排列,对于它的每一个子序列 \(s[1..p]\),对于每一个 \(i \in [1,p-1]\),给 \(s[i],s[i+1]\) 间的每一个值对应的桶 \(+1\),求最终每个桶的值. ...

  9. HDU3887(树dfs序列+树状数组)

    Counting Offspring Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

随机推荐

  1. 初识Python-1

    1,计算机基础. 2,python历史. 宏观上:python2 与 python3 区别: python2 源码不标准,混乱,重复代码太多, python3 统一 标准,去除重复代码. 3,pyth ...

  2. mysql创建数据库命令

    CREATE DATABASE IF NOT EXISTS yourdbname DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

  3. MYSQL mydumper & myloader

    第三方逻辑备份工具myduper和myloader | xiaoyu的数据库小窝-技术交流http://www.dbaxiaoyu.com/archives/1643 myloader原理0 - ze ...

  4. java list 去重

    Guava ImmutableSet源码去重处理,Hash处理 - 汪小哥 - CSDN博客 https://blog.csdn.net/u012881904/article/details/6895 ...

  5. 渗透测试平台bwapp简单介绍及安装

    先来介绍一下bwapp bwapp是一款非常好用的漏洞演示平台,包含有100多个漏洞 SQL, HTML, iFrame, SSI, OS Command, XML, XPath, LDAP, PHP ...

  6. [转帖]cmd批处理常用符号详解

    cmd批处理常用符号详解 https://www.jb51.net/article/32866.htm 很多符号 还是不清楚的.. 批处理能够极大的提高 工作效率 需要加强深入学习.   1.@一般在 ...

  7. 120. 单词接龙 (BFS)

    描述 给出两个单词(start和end)和一个字典,找到从start到end的最短转换序列 比如: 每次只能改变一个字母. 变换过程中的中间单词必须在字典中出现. 如果没有转换序列则返回0. 所有单词 ...

  8. 6s ios9.0平台 微信小程序的fixed定位兼容性问题

    如果不设置top和left的话  就会出现不显示问题

  9. Hbase获取流程

    1\\.客户端chou操作 2.服务器dauncaozuo操作 3\存储优化

  10. python爬虫scrapy之登录知乎

    下面我们看看用scrapy模拟登录的基本写法: 注意:我们经常调试代码的时候基本都用chrome浏览器,但是我就因为用了谷歌浏览器(它总是登录的时候不提示我用验证码,误导我以为登录时不需要验证码,其实 ...