题目链接:hdu_5193_Go to movies Ⅱ

题意:

有n个人站成一排,每个人的身高为Hi。每次有人加入或者有人离开,就要判断有多少人站反了(i < j&&Hi>Hj) 
第一行n,m,接下来n个整数(n,m<=2e4) 
接下来m行, 
0 x y 表示有一个身高为y的人插在x后面,x=0表示插在最前面。(1≤y≤n) 
1 x 表示第x个人(从左到右)离开。

题解:

官方题解:

添加或者删除一个元素时,维护逆序对时,需要知道在它之前有多少个数比它大,在它之后有多少个数比他小。有下标和权值两个维度,可以使用两个数据结构嵌套。题目中n=20000,范围不大,外层可以使用分块维护下标,这样添加和删除元素的时候, 
也很方便,直接暴力。查找权值个数时,使用树状数组比较方便。内层通过树状数组维护权值。设每块的大小为S,那么删除或者添加元素时,维护逆序对数的复杂度是O(S+P∗logn),S是块内直接暴力更新逆序对的代价, 
​P/S∗logn在前面块找比它大和在后面块中找比它小的代价,P表示当前元素的个数。为了使这两部分复杂度尽量均摊让S=P/S∗logn,S取根号Plogn 
​。直接通过分块暴力添加和删除时,块的大小会退化,需要重构,。重构一次的复杂度是S*logn, 总的重构复杂度是,与添加和删除总的复杂度一至。因此整个问题的复杂度为O(m√nlogn).

 #include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;i++)
using namespace std; const int N=,sqr=;
int ans,tot,n,flag,op,x,y,m; inline void add(int *c,int x,int v){while(x<=n)c[x]+=v,x+=x&-x;} inline int sum(int *c,int x){int an=;while(x>)an+=c[x],x-=(x&-x);return an;} struct node
{
int dt[sqr+],sz,c[N],nxt,pre;
void init(){memset(c,,sizeof(c)),sz=,pre=,nxt=;}
}b[]; int getpos(int &x)
{
int i=;
while(b[i].sz<x&&b[i].nxt)x-=b[i].sz,i=b[i].nxt;
return i;
} int cal(int x)
{
int an=;
int id=getpos(x);
F(i,,x-)if(b[id].dt[i]>b[id].dt[x])an++;
F(i,x+,b[id].sz)if(b[id].dt[i]<b[id].dt[x])an++;
for(int i=;i!=id;i=b[i].nxt)
an+=sum(b[i].c,n)-sum(b[i].c,b[id].dt[x]);
for(int i=b[id].nxt;i!=;i=b[i].nxt)
an+=sum(b[i].c,b[id].dt[x]-);
return an;
} void del(int x){
ans-=cal(x);
int id=getpos(x);
add(b[id].c,b[id].dt[x],-);
F(i,x+,b[id].sz)b[id].dt[i-]=b[id].dt[i];
b[id].sz--;
if(b[id].sz==)//删除块
{
int pre=b[id].pre,net=b[id].nxt;
b[net].pre=pre,b[pre].nxt=net;
}
} void ins(int x,int y)
{
int xx=x;
if(flag==)
{
b[].init(),b[].dt[++b[].sz]=y;
add(b[].c,b[].dt[],),flag=;
return;
}
int id=getpos(x);//在第几个块
if(b[id].sz==sqr)//块分裂
{
b[++tot].init(),b[id].sz++;
int cnt=;
for(int i=b[id].sz;i>x;i--)
b[id].dt[i]=b[id].dt[i-];
b[id].dt[x]=y;
add(b[id].c,b[id].dt[x],);
int len=b[id].sz/;
F(i,len+,b[id].sz)
{
b[tot].dt[++cnt]=b[id].dt[i];
add(b[tot].c,b[id].dt[i],);
add(b[id].c,b[id].dt[i],-);
}
b[tot].sz=cnt,b[tot].nxt=b[id].nxt;
b[id].nxt=tot,b[id].sz=len,b[tot].pre=id;
}
else{
b[id].sz++;
for(int i=b[id].sz;i>x;i--)
b[id].dt[i]=b[id].dt[i-];
b[id].dt[x]=y;
add(b[id].c,b[id].dt[x],);
}
ans+=cal(xx);
} int main(){
while(~scanf("%d%d",&n,&m))
{
ans=,tot=,b[].sz=,flag=;
F(i,,n)scanf("%d",&y),ins(i,y);
F(i,,m)
{
scanf("%d",&op);
if(op==)scanf("%d%d",&x,&y),ins(x+,y);
else scanf("%d",&x),del(x);
printf("%d\n",ans);
}
}
return ;
}

hdu_5193_Go to movies Ⅱ(带插入删除的逆序对,块状链表)的更多相关文章

  1. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

  2. BZOJ 3295: [Cqoi2011]动态逆序对 [CDQ分治]

    RT 传送门 首先可以看成倒着插入,求逆序对数 每个数分配时间(注意每个数都要一个时间)$t$,$x$位置,$y$数值 $CDQ(l,r)$时归并排序$x$ 然后用$[l,mid]$的加入更新$[mi ...

  3. [BZOJ3295] [Cqoi2011]动态逆序对(带修改主席树)

    题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...

  4. 【BZOJ】3065: 带插入区间K小值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...

  5. 「C语言」单链表/双向链表的建立/遍历/插入/删除

    最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合, ...

  6. python Trie树和双数组TRIE树的实现. 拥有3个功能:插入,删除,给前缀智能找到所有能匹配的单词

    #coding=utf- #字典嵌套牛逼,别人写的,这样每一层非常多的东西,搜索就快了,树高26.所以整体搜索一个不关多大的单词表 #还是O(). ''' Python 字典 setdefault() ...

  7. 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)

    3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...

  8. [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树

    刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...

  9. [LeetCode] Insert Delete GetRandom O(1) - Duplicates allowed 常数时间内插入删除和获得随机数 - 允许重复

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

随机推荐

  1. ACM沈化校赛

    答对两道题,因为比赛经验原因明明可以对四道,在这两道题又浪费过多时间,成绩不理想,但也是累积了一下经验.

  2. EasyCHM(CHM电子书制作工具) v3.84.545 绿色版

    软件名称:EasyCHM(CHM电子书制作工具) v3.84.545 绿色版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 2.78MB 图片预览: 软件 ...

  3. uoj 55 紫荆花之恋 动态点分治+替罪羊式重构+treap

    每插入一个点,直接把它当做重心插入原树,当做是动态点分树一样维护 但这样深度会越来越大,所以我们用类似替罪羊的方法 当树失去平衡时,对子树进行一次点分,保证复杂度 #include <cstdi ...

  4. GrowingIO 2016 数据驱动增长大会—— 一起做增长英雄

    GrowingIO 2016 数据驱动增长大会,首次聚齐了增长黑客之父 Sean Ellis .世界前十位前沿数据科学家张溪梦等数十位中美顶尖增长实践者: 链家.点融网.Camera360.量化派.北 ...

  5. [UWP小白日记-6]页面跳转过度动画

    前言 在学习中发现页面导航默认是没有过度动画的,直接就导航过去太粗暴了( ̄へ ̄),于是打算上动画结果不言而喻自己进了坑完全不懂动画,然后就是各种疯狂(´・_・`)的搜索资料看了后终于有点头绪. 再后来 ...

  6. Scheme入门

    目前选择的是DrRacket作为IDE,可以去网上搜索下载. 打开软件后,输入如下代码进行 helloworld #lang scheme ;The first program (begin (dis ...

  7. Chapter 17_4 终结器

    Lua中的垃圾回收主要是针对Lua对象,但是也可以做一些额外的资源管理工作. 可以为表设定垃圾收集的元方法(对于完全用户数据,则需要使用C API),该元方法称为 终结器. Lua用"__g ...

  8. C# DataRow[]转换DataTable

    DataTable dt = ... DataRow[] dr = dt.Select("ID=14"); dt = dr.CopyToDataTable();

  9. request相关研究

    一.什么是httpservletrequest 用来处理一个对Servlet的HTTP格式的请求信息. 二.httpservletrequest的作用是什么 优点: 公共接口类HttpServletR ...

  10. (repost)在ARM Linux内核中增加一个新的系统调用

    实验平台内核版本为4.0-rc1,增加一仅仅打印Hello World的syscall,最后我们在用户空间swi验证 实验平台内核版本为4.0-rc1,增加的系统调用仅仅是简单打印一个Hello Wo ...