HDU5196--DZY Loves Inversions 树状数组 逆序数
题意查询给定[L, R]区间内 逆序对数 ==k的子区间的个数。
我们只需要求出 子区间小于等于k的个数和小于等于k-1的个数,然后相减就得出答案了。
对于i(1≤i≤n),我们计算ri表示[i,ri]的逆序对数小于等于K,且ri的值最大。(ri对应代码中的cnt数组)
显然ri单调不降,我们可以通过用两个指针扫一遍,利用树状数组计算出r数组。
对于每个询问L,R,我们要计算的是∑i=LR[min(R,ri)−i+1]
由于ri具有单调性,那我们直接在上面二分即可,然后记一个前缀和(s数组)。
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
const int maxn = 1e5+;
int n, q, tot, a[maxn];
ll k, vec[maxn];
int lowbit (int x)
{
return x & -x;
}
ll arr[maxn];
int M ;
void modify(int x, int d)
{
while (x < M)
{
arr[x] += d;
x += lowbit(x);
}
}
ll sum(int x)
{
ll res = ;
while (x)
{
res += arr[x];
x -= lowbit(x);
}
return res;
}
ll cnt[][maxn];
ll s[][maxn];
ll solve (int L, int R, ll x, int w) // 小于等于x的数量
{
if (x < )
return ;
//int tmp = 0;
int tmp = lower_bound(cnt[w]+L, cnt[w]+R+, (ll)R) - cnt[w];
while (tmp >= R+) // cnt数组中所有数都小于 R时,,得到的tmp是大于R+1的
tmp--;
while (cnt[w][tmp] > R && tmp >= L)
tmp--;
if (tmp < L)
return (ll)R*(ll)(R-L+) - (ll)(L+R)*(ll)(R-L+)/;
return s[w][tmp] - s[w][L-] - (ll)(R-tmp)*(ll)(R+tmp+)/+ (ll)(R-tmp)*(ll)R;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt", "w", stdout);
#endif
while (~scanf ("%d%d%I64d", &n, &q, &k))
{
M = n + ;
memset(arr, , sizeof (arr));
memset(cnt, , sizeof (cnt));
memset(s, , sizeof(s));
for (int i = ; i < n; i++)
{
scanf ("%I64d", vec+i);
a[i] = vec[i];
}
sort (vec, vec+n);
tot = unique(vec, vec+n) - vec;
for (int i = ; i < n; i++)
{
a[i] = lower_bound(vec, vec+tot, a[i]) - vec + ; //离散化
}
ll res = ;
//小于等于k
for (int i = , j = ; i < n; i++)
{
for ( ; j < n && res <= k; j++)
{
res += (j - i) - sum(a[j]);
modify(a[j], );
}
if (res >= k)
cnt[][i] = (res > k ? max(,j --): j-) ; // -1是因为 j先加了一下, 才跳出 循环的
else
cnt[][i] = j--;
s[][i] = s[][i-] + cnt[][i] - (i);
modify(a[i], -);
res -= sum(a[i]-);
} //小于等于k-1
res = ;
for (int i = , j = ; i < n; i++)
{
for ( ; j < n && res <= (k-); j++)
{
res += (j-i) - sum(a[j]);
modify(a[j], );
}
if (res >= k-)
cnt[][i] = (res > (k-) ? max(j--,) : j-);
else
cnt[][i] = j--; s[][i] = s[][i-] + cnt[][i] - (i);
modify(a[i], -);
res -= sum(a[i]-);
}
for (int i = ; i < q; i++)
{
int u, v;
scanf ("%d%d", &u, &v);
u--, v--;
if (u > v)
swap(u, v);
ll ans1 = solve(u, v, k, );
ll ans2 = solve(u, v, k-, );
if (k == )
ans1 += (v-u+); // 考虑形如[a, a]的区间
printf("%I64d\n", ans1-ans2 );
}
}
return ;
}
HDU5196--DZY Loves Inversions 树状数组 逆序数的更多相关文章
- HDU 4911 (树状数组+逆序数)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4911 题目大意:最多可以交换K次,就最小逆序对数 解题思路: 逆序数定理,当逆序对数大于0时,若ak ...
- hdu2838Cow Sorting(树状数组+逆序数)
题目链接:点击打开链接 题意描写叙述:给定一个长度为100000的数组,每一个元素范围在1~100000,且互不同样,交换当中的随意两个数须要花费的代价为两个数之和. 问怎样交换使数组有序.花费的代价 ...
- HDU3465 树状数组逆序数
Life is a Line Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)T ...
- [树状数组+逆序对][NOIP2013]火柴排队
火柴排队 题目描述 涵涵有两盒火柴,每盒装有n根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ (ai-bi)2,i=1,2,3,. ...
- hdu 5497 Inversion 树状数组 逆序对,单点修改
Inversion Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5497 ...
- Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对
题目:http://codevs.cn/problem/3286/ 3286 火柴排队 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : ...
- Bzoj 2789: [Poi2012]Letters 树状数组,逆序对
2789: [Poi2012]Letters Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 278 Solved: 185[Submit][Stat ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- Bzoj 3289: Mato的文件管理 莫队,树状数组,逆序对,离散化,分块
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1539 Solved: 665[Submit][Status][Di ...
随机推荐
- ListView的优化
1. ListView须要设置adapter,它的item是通过adapter的方法getView(int position, View convertView, ViewGroup parent)获 ...
- LeetCode Maximum Product Subarray 解题报告
LeetCode 新题又更新了.求:最大子数组乘积. https://oj.leetcode.com/problems/maximum-product-subarray/ 题目分析:求一个数组,连续子 ...
- Android项目实战--手机卫士18--读取用户的短信内容以及短信备份
我们今天要说的就是我们手机卫士里面的高级工具里面的短信备份功能啦,其实这个软件备份的功能也很简单,就是把用户的短信读出来,然后写到一个xml或者数据库里面, 但我们这里的是读取到xml里面的. 首先我 ...
- Python:代码调试的好帮手sys._getframe()
python 的调试,令人非常忧伤,通过将输出路径打印的方式,可以提高很大的方便性: import sys #coding=utf-8 def get_cur_info(): print sys._g ...
- ajax与Servlet
1.后台返回text类型的数据 <%@ page language="java" import="java.util.*" pageEncoding=&q ...
- call和apply区别
call和apply 基本上是一个意思 区别在于call的第二个参数可以是任意的类型,而apply的第二个参数必须是数组,也可以是arguments.call方法:语法:call(thisObj,Ob ...
- javascript基础之变量和函数声明
1.变量的声名 window.name = 'gjlin' ; //全局变量 直接name = 'gjlin' 也表示全局变量,但是建议使用window.name = 'gjlin' 这种形式表示 ...
- css控制背景图片在浏览器中居中,下拉浏览器的时候背景图一直不变
如 http://www.gm.com/ css样式如下 ;;} #con{ position:absolute; ; ; height:100%; width:100%; background-im ...
- 一个控制台贪吃蛇小游戏(wsad控制移动)
/******************************************** * 程序名称:MR.DUAN 的贪吃蛇游戏(链表法) * 作 者:WindAutumn <flutti ...
- Linux shell 脚本中”2>&1″的含义解释
脚本是:nohup /mnt/Nand3/H2000G >/dev/null 2>&1 & 对于& 1 更准确的说应该是文件描述符 1,而1 一般代表的就是 ...