UVA 11990 ``Dynamic'' Inversion (线段树套BIT,分治)
题目要求可转化为查询一个区间内有多少数比val大(或者小)。
区间用线段树分解(logN),每个区间维护一rank树。
rank可用BIT查询,往BIT里面插值,为了保证不同区间的BIT互不影响要先离散。
首先进行分治,分治的同时归并排序完成离散并计算保存出每个元素和其他元素构成的逆序对iv[i]。(据说这叫归并树
初始值将所有iv求和,一个对被算了两次所以除以二。
每次删除元素val就减去val对应的逆序对。
减去iv[val],但是多减去了和之前删掉元素构成的逆序对(这些逆序对已经算过一次)。
所以把删掉的元素加到线段树里面。
减去当前iv[val]之后,查询并加上当前元素val和之前位置以及之后位置构成逆序对。
复杂度
O(nlogn)预处理,O(m*logn*logn)回答
#include<bits/stdc++.h>
using namespace std; const int maxn = 2e5+, LogN = ; typedef long long ll;
ll invPair;
int a[maxn],p[maxn];
int iv[maxn];
int n; int s[maxn<<];
int C[LogN][maxn];
int Set[LogN][maxn]; #define para int o = 1, int l = 1,int r = n,int dep = 0
#define lo (o<<1)
#define ro (o<<1|1)
#define TEMP int mid = (l+r)>>1, lc = lo, rc = ro;
#define lsn lc, l, mid, dep+1
#define rsn rc, mid+1, r, dep+1 #define lb(x) ((x)&-(x))
int sum(int C[],int x)
{
int re = ;
while(x>){
re += C[x];
x -= lb(x);
}
return re;
} void add(int C[],int x,int d,int r)
{
while(x<=r){
C[x] += d;
x += lb(x);
}
} int qpos;
int ql,qr,val;
void queryPrefix(para)
{
if(<=l&&r<=qr){
int pos = upper_bound(Set[dep]+l,Set[dep]+r+,val)-Set[dep]-l;//等于等于val的最大元素的编号
invPair += s[o] - sum(C[dep]+l-,pos);//得到大于val的元素个数
}else {
TEMP
queryPrefix(lsn);
if(qr>mid) queryPrefix(rsn);
}
} void querySuffix(para)
{
if(ql<=l&&r<=n){
int pos = lower_bound(Set[dep]+l,Set[dep]+r+,val)-Set[dep]-l;//严格小于val的元素的编号
invPair += sum(C[dep]+l-,pos);
}else {
TEMP
if(ql<=mid) querySuffix(lsn);
querySuffix(rsn);
}
} void modify(para)
{
s[o]++;
if(l == r){
C[dep][l] = ;
}else{
TEMP
if(qpos<=mid) modify(lsn);
else modify(rsn);
int pos = upper_bound(Set[dep]+l,Set[dep]+r+,val)-Set[dep]-l;//val在set里,从1开始编号
add(C[dep]+l-,pos,,r-l+);//l-1是0号位,容纳r-l+1个元素
}
} //为保证BIT之间互不影响,merge_sort离散,同时计算逆序对
void discretize(para)
{
s[o] = ;
memset(C[dep]+l,,sizeof(int)*(r-l+));
if(l == r) {
Set[dep][l] = a[l];
return;
}else {
TEMP;
discretize(lsn);
discretize(rsn);
int p = l, q = mid+, k = l;
while(p<=mid || q<=r){
if(q > r|| (p <= mid && Set[dep+][p] <= Set[dep+][q]) ){
iv[Set[dep+][p]] += k-p;//和后面的数构成逆序对
Set[dep][k++] = Set[dep+][p++];
}else {
iv[Set[dep+][q]] += mid-p+;//和前面的数构成逆序对
Set[dep][k++] = Set[dep+][q++];
}
}
}
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int m;
while(~scanf("%d%d",&n,&m)){
memset(iv+,,sizeof(int)*n);
for(int i = ; i <= n; i++){
scanf("%d",a+i);
p[a[i]] = i;
}
invPair = ;
discretize();
for(int i = ; i <= n; i++){
invPair += iv[i];
}
invPair >>= ;
while(m--){
scanf("%d",&val);
printf("%lld\n",invPair);
invPair -= iv[val];
qr = p[val]-;
ql = p[val]+;
if(qr>=) queryPrefix();
if(ql<=n) querySuffix();
qpos = p[val];
modify();
}
}
return ;
}
UVA 11990 ``Dynamic'' Inversion (线段树套BIT,分治)的更多相关文章
- UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)
[题目链接] UVA11990 [题目大意] 给出一个数列,每次删去一个数,求一个数删去之前整个数列的逆序对数. [题解] 一开始可以用树状数组统计出现的逆序对数量 对于每个删去的数,我们可以用线段树 ...
- UVA 11990 ``Dynamic'' Inversion 动态逆序对
``Dynamic'' Inversion Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/index ...
- uva 12003 Array Transformer (线段树套平衡树)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- BZOJ.1901.Dynamic Rankings(线段树套平衡树 Splay)
题目链接or Here 题意:n个数,有两个操作:1.修改某个数为v:2.询问一段区间第k小的数 如果没有修改,则可以用线段树,每个节点P[a,b]存储大小为b-a+1的数组,代表其中的数 同时,这个 ...
- UVA 11990 ``Dynamic'' Inversion (序列分治)
26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大. 本来想学习一下cdq分治的,看到论文上的凸包.斜率就暂时放一边了,只知道 ...
- UVA 11990 `Dynamic'' Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树
之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池 ...
- 树套树Day1线段树套平衡树bzoj3196
您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...
随机推荐
- Black Beauty
Chapter 1 My Early Home While I was young, I live upon my mother's milk, as I could not eat grass. W ...
- SCUT - 337 - 岩殿居蟹 - 线段树 - 树状数组
https://scut.online/p/337 这个东西是个阶梯状的.那么可以考虑存两棵树,一棵树是阶梯的,另一棵树的平的,随便一减就是需要的阶梯. 优化之后貌似速度比树状数组还惊人. #incl ...
- rgbdslam_v2编译过程中引起的needed by错误
Ubuntu16.04,ROS kinectic 报错信息为“ make[2]: *** No rule to make target '/home/william/slam/g2o/lib/libg ...
- CodeForces 116C 【BFS】
思路: 求所有树的最大高度? 注意:所有树从树根开始? #include <bits/stdc++.h> using namespace std; typedef long long LL ...
- 【转】C# String 前面不足位数补零的方法
源地址:http://www.cnblogs.com/zhangqs008/archive/2012/02/01/2341078.html
- CF 979D Kuro and GCD and XOR and SUM(异或 Trie)
CF 979D Kuro and GCD and XOR and SUM(异或 Trie) 给出q(<=1e5)个操作.操作分两种,一种是插入一个数u(<=1e5),另一种是给出三个数x, ...
- uoj #185. 【ZJOI2016】小星星
#185. [ZJOI2016]小星星 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有 nn 颗小星星,用 mm 条彩色的细线串了起来,每条细线连着两颗小星星.有一天她发现,她的饰品被破坏 ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT)
传送门 FlashHu大佬太强啦%%% 首先,我们可以根据每一个点的权值为$1$的儿子的个数把每个点记为$0~3$,表示这一个点的点权 先考虑一下暴力的过程,假设从$0$变为$1$,先更改一个叶子结点 ...
- jmeter 签名MD5生成(转)
请求接口需要同时发送签名,签名定义为: 可以看出签名就是把用户的密码 .用户名 和签名key生成一个md5串就可以了 刚好jmeter 有个md5 生成,生成前需要获取name ,password k ...
- AD按键-矩阵按键-独立按键:
原理:利用数组分压+AD采集: 优点:一个IO口可以做成多个按键,节省IO口(矩阵键盘在>4时优点才能体现出来):可备用作为AD基准输入. 缺点:不能做成组合按键(或者电阻要精确选择):且离IO ...