题目分析:

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

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

令分块大小为$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. Method not found: !!0[] System.Array.Empty()错误

    最近由于公司项目需要将之前支持的TLS1.0改成更安全的TLS1.2,而公司现有项目都是老系统,有的是.NET FrameWork 4.0,有的是.NET FrameWork3.5,但是TLS1.2默 ...

  2. POJ - 3264 线段树模板题 询问区间最大最小值

    这是线段树的一个模板题,给出一串数字,然后询问区间的最大最小值. 这个其实很好办,只需把线段树的节点给出两个权值,一个是区间的最小值,一个是区间的最大值,初始化为负无穷和正无穷,然后通过不断地输入节点 ...

  3. Python学习第十篇——函数初步

    def make_album(name,album_name,song_nums = 1): dict_album = {name:[album_name]} if int(song_nums) &g ...

  4. iOS数据存储-钥匙串存储

    2017.11.20 14:41* 字数 227 阅读 678评论 0喜欢 0 钥匙串介绍   1. 表示设备唯一号的标识,在IOS7中要么被禁止使用,要么重新安装程序后两次获取的标识符不一样. 2. ...

  5. 软件工程(FZU2015) 赛季得分榜,第10回合(alpha冲刺)

    SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分=团队得分+个人贡献分 个人贡献分: 个人 ...

  6. MySQL 性能调优之SQL

    原文:http://bbs.landingbj.com/t-0-245451-1.html 对于SQL的优化,我们主要提供调整执行计划.优化SQL的方法有:缩短访问的路径.尽早过滤数据.尽可能减少排序 ...

  7. IdentityServer4【Topic】之定义资源

    Defining Resources 定义资源 你在系统中通常定义的第一件事是你想要保护的资源.这可能是你的用户的身份信息,比如个人资料数据或电子邮件地址,或者访问api. 你可以通过C#对象模型(内 ...

  8. C#复习笔记(5)--C#5:简化的异步编程(异步编程的深入分析)

    首先,阐明一下标题的这个“深入分析”起得很惭愧,但是又不知道该起什么名字,这个系列也主要是做一些复习的笔记,供自己以后查阅,如果能够帮助到别人,那自然是再好不过了. 然后,我想说的是异步方法的状态机真 ...

  9. Azure系列2.1.12 —— CloudBlobDirectory

    (小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...

  10. [转帖]中关村:LED屏幕和OLED屏幕有什么区别?答案在这里

    LED屏幕和OLED屏幕有什么区别?答案在这里   中关村在线 01-0810:40 目前的电视市场,更新换代的频率越来越快,无论是国产品牌还是合资品牌,都不约而同的推出了全新产品.这离不开人们对更好 ...