题目描述

我早已习惯你不在身边,
人间四月天 寂寞断了弦。
回望身后蓝天,
跟再见说再见……
某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现
她们排成了一个序列,每个妹子有一个美丽度。
Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:"你知道区间
[l,r]中妹子们美丽度的逆序对数吗?"
蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:"强制在线。"
请你帮助一下Autumn吧。
给定一个正整数序列a,对于每次询问,输出al...ar中的逆序对数,强制在线。

输入

第一行包括一个整数n(1<=n<=50000),表示数列a中的元素数。
第二行包括n个整数a1...an(ai>0,保证ai在int内)。
接下来一行包括一个整数m(1<=m<=50000),表示询问的个数。
接下来m行,每行包括2个整数l、r(1<=l<=r<=n),表示询问al...ar中的逆序对数(若ai>aj且i<j,则为一个逆序对)。
l,r要分别异或上一次询问的答案(lastans),最开始时lastans=0。保证涉及的所有数在int内。

输出

对每个询问,单独输出一行,表示al...ar中的逆序对数。

样例输入

4
1 4 2 3
1
2 4

样例输出

2


题解

分块+树状数组+主席树

由于题目强制在线,所以不能离线乱搞了。

正常来说,在线查询区间内比某数大/小的数的个数,使用的数据结构是主席树。

然而这样依然要查询询问区间内每个元素,这样时间复杂度还是不能下降。

我们想到可以使用分块预处理,查询时只查询块外元素,能够使时间复杂度降低。

具体地,设f[i][j]表示从第i块开始,到第j个位置结束的逆序对数。这样枚举每个i,就能够在$O(n\log n)$的时间内预处理。

对于每个查询,找到查询区间内第一个整块,根据f数组得到它到区间右端的逆序对数,这样剩下的就只有区间左端块外元素,使用主席树查询即可。

总时间复杂度为$O((n+m)\sqrt n\log n)$,另外听大爷说本题卡常,所以在预处理时需要使用树状数组。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 100010
using namespace std;
int a[N] , v[N] , sum[250][N] , f[N] , n , ls[N << 4] , rs[N << 4] , si[N << 4] , root[N] , tot;
void update(int x)
{
int i;
for(i = x ; i <= n ; i += i & -i) f[i] ++ ;
}
int query(int x)
{
int i , ans = 0;
for(i = x; i ; i -= i & -i) ans += f[i];
return ans;
}
void insert(int p , int l , int r , int x , int &y)
{
y = ++tot , si[y] = si[x] + 1;
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid) rs[y] = rs[x] , insert(p , l , mid , ls[x] , ls[y]);
else ls[y] = ls[x] , insert(p , mid + 1 , r , rs[x] , rs[y]);
}
int calc(int p , int l , int r , int x , int y)
{
if(l > p) return 0;
if(r <= p) return si[y] - si[x];
int mid = (l + r) >> 1;
return calc(p , l , mid , ls[x] , ls[y]) + calc(p , mid + 1 , r , rs[x] , rs[y]);
}
int main()
{
int m , i , j , si , last = 0 , x , y , ans;
scanf("%d" , &n) , si = (int)sqrt(n);
for(i = 0 ; i < n ; i ++ ) scanf("%d" , &a[i]) , v[i] = a[i];
sort(v , v + n);
for(i = 0 ; i < n ; i ++ ) a[i] = lower_bound(v , v + n , a[i]) - v , insert(a[i] , 0 , n - 1 , root[i] , root[i + 1]);
for(i = 0 ; i <= n / si ; i ++ )
{
memset(f , 0 , sizeof(f)) , update(n - a[i * si]);
for(j = i * si + 1 ; j < n ; j ++ ) sum[i][j] = sum[i][j - 1] + query(n - a[j] - 1) , update(n - a[j]);
}
scanf("%d" , &m);
while(m -- )
{
scanf("%d%d" , &x , &y) , x = (x ^ last) - 1 , y = (y ^ last) - 1 , ans = 0;
if(x / si == y / si)
for(i = y - 1 ; i >= x ; i -- )
ans += calc(a[i] - 1 , 0 , n - 1 , root[i + 1] , root[y + 1]);
else
{
ans += sum[x / si + 1][y];
for(i = (x / si + 1) * si - 1 ; i >= x ; i -- )
ans += calc(a[i] - 1 , 0 , n - 1 , root[i + 1] , root[y + 1]);
}
printf("%d\n" , last = ans);
}
return 0;
}

【bzoj3744】Gty的妹子序列 分块+树状数组+主席树的更多相关文章

  1. P1972 [SDOI2009]HH的项链[离线+树状数组/主席树/分块/模拟]

    题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链 ...

  2. BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树

    BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树 题意: 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i, ...

  3. zoj2112 树状数组+主席树 区间动第k大

    Dynamic Rankings Time Limit: 10000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu Subm ...

  4. 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  5. BZOJ_2120_数颜色_Set+树状数组+主席树

    BZOJ_2120_数颜色_Set+树状数组+主席树 Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L ...

  6. BZOJ 3744: Gty的妹子序列 【分块 + 树状数组 + 主席树】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=3744 3744: Gty的妹子序列 Time Limit: 20 Sec  Memory ...

  7. BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)

    题面传送门 题目大意:给你一个序列,多次询问,每次取出一段连续的子序列$[l,r]$,询问这段子序列的逆序对个数,强制在线 很熟悉的分块套路啊,和很多可持久化01Trie的题目类似,用分块预处理出贡献 ...

  8. [luogu2617][bzoj1901][Zju2112]Dynamic Rankings【树套树+树状数组+主席树】

    题目网址 [传送门] 题目大意 请你设计一个数据结构,支持单点修改,区间查询排名k. 感想(以下省略脏话inf个字) 真的强力吹爆洛谷数据,一般的树套树还给我T了一般的点,加强的待修主席树还给我卡了几 ...

  9. ZOJ 2112 Dynamic Rankings(树状数组+主席树)

    题意 \(n\) 个数,\(m\) 个操作,每次操作修改某个数,或者询问某个区间的第 \(K\) 小值. \(1 \leq n \leq 50000\) \(1 \leq m \leq 10000\) ...

随机推荐

  1. ZOJ 1729 Hidden Password (字符串最小表示)

    以前听过,不知道是什么,其实就是字符串首尾相连成一个环,n种切法求一个字典序最小的表示. 朴素算法大家都懂.O(n)的算法代码非常简单,最主要的思想是失配的时候尽可能大的移动指针. 另外附上一个不错的 ...

  2. pycharm创建工程的两种形式:virtualenv环境和系统默认编译器

    转自:http://swiftlet.net/archives/3151 pycharm创建工程的时候可以选择编译器,如下图所示: 上图表示创建工程有两种方式:第一种是利用:virtualenv,第二 ...

  3. 2018.3.3 多线程中继承Thread 和实现Runnable接口 的比较(通过售票案例来分析)

    多线程中继承Thread 和实现Runnable接口 的比较(通过售票案例来分析) 通过Thread来实现 Test.java package com.lanqiao.demo4; public cl ...

  4. 剑指offer题目分类

    1. 链表 1. 从尾到头打印链表 2. 链表中倒数第k个结点 3. 反转链表 4. 合并两个排序的链表 5. 复杂链表的复制 6. 复杂链表的复制 7. 两个链表的第一个公共结点 8. 链表中环的入 ...

  5. 汉明码(Hamming Code)原理及实现

    汉明码实现原理 汉明码(Hamming Code)是广泛用于内存和磁盘纠错的编码.汉明码不仅可以用来检测转移数据时发生的错误,还可以用来修正错误.(要注意的是,汉明码只能发现和修正一位错误,对于两位或 ...

  6. tcp 高性能服务, netty,mqtt

    1. io 线程不要有比较长的服务. 全部异步化. [1] netty 权威指南上只是说业务复杂时派发到业务线程池种. 共用的线程池最好都轻量. 多层线程池后, 下层的可以进行隔离. 这个是 mqtt ...

  7. lua 使用递归查找键值

    function cc.exports.findValueByTbl(tbl,key)--递归方法,用于查找tbl中对应的键值 for k,v in pairs(tbl) do if k == key ...

  8. 【转】VS2010下MFC的串口编程

    串口通信简介 一般来说,计算机都有一个或多个串行端口,这些串口提供了外部设备与PC进行数据传输和通信的通道,在CPU和外设之间充当解释器的角色.当字符数据从CPU发送给外设时,这些字符数据将被转换成串 ...

  9. Codeforces 517 #B

    http://codeforces.com/contest/1072/problem/B 开始想的只有搜索,时间复杂度$O(4^n)$,明显有问题. 想了半个小时没有思路,然后想到了正难则反,就开始步 ...

  10. MySQL查询显示连续的结果

    #mysql中 对于查询结果只显示n条连续行的问题# 在领扣上碰到的一个题目:求满足条件的连续3行结果的显示 X city built a new stadium, each day many peo ...