bzoj2141 树状数组套Treap树
题目大意是在能够改变两个数的位置的情况下计算逆序对数
这因为是动态记录逆序对
本来单纯逆序对只要用树状数组计算即可,但这里因为更新,所以利用TReap树的删点和增加点来进行更新
大致是把每个树状数组所管理的点都放在对应的Treap树下,
这样x-=lowbit(x)下来,正好访问到是所有比他小范围下的点了
然后根据每棵访问到的Treap树有多少个节点是比当前值小的即可
每次交换ai , aj , (i<j)只要考虑(i,j)范围内比ai大的数,比aj小的数,然后加加减减即可
如果ai!=aj也是要加减1
- #include <bits/stdc++.h>
- using namespace std;
- #define N 20005
- struct Node{
- int l , r , val , sz , pri , cnt;
- //cnt表示当前位置相同的数有多少个,pri表示优先级,sz表示这棵子树所含有的节点总个数
- Node(){
- l = r = ;
- cnt = sz = , pri = rand();
- val = ;
- }
- Node(int v){
- Node();
- val = v;
- }
- };
- #define ls node[x].l
- #define rs node[x].r
- namespace Treap{
- int tot;//Treap Node节点的总个数
- int A[N];//有n棵treap树,A[]表示每棵treap树的起始位置
- Node node[N*];
- void init(){
- node[] = Node();
- node[].cnt = node[].sz = ;
- memset(A , , sizeof(A));
- tot = ;
- }
- int newNode(int v){
- ++tot;
- node[tot].cnt = node[tot].sz = ;
- node[tot].l = node[tot].r = ;
- node[tot].pri = rand();
- node[tot].val = v;
- return tot;
- }
- void push_up(int x) {
- // cout<<"here: "<<x<<" "<<ls<<" "<<rs<<endl;
- if(x>)
- node[x].sz = node[ls].sz+node[rs].sz+node[x].cnt;
- }
- void rotL(int &x){
- int y = rs;
- rs = node[y].l;
- node[y].l = x;
- push_up(x);
- push_up(y);
- x = y;
- }
- void rotR(int &x){
- int y = ls;
- ls = node[y].r;
- node[y].r = x;
- push_up(x);
- push_up(y);
- x = y;
- }
- void insert(int &x , int v){
- // cout<<x<<" "<<v<<endl;
- if(x == ) x = newNode(v);
- else if(node[x].val>v){
- insert(ls , v);
- if(node[ls].pri>node[x].pri) rotR(x);
- }
- else if(node[x].val<v){
- insert(rs , v);
- if(node[rs].pri>node[x].pri) rotL(x);
- }
- else node[x].cnt++;
- push_up(x);
- // cout<<x<<" "<<v<<" "<<"endd"<<endl;
- }
- void erase(int &x , int v){
- if(x == ) return ;
- else if(v<node[x].val) erase(ls , v);
- else if(v>node[x].val) erase(rs , v);
- else {
- node[x].cnt--;
- if(node[x].cnt<=){
- if(ls==&&rs==) x = ;
- else if(ls == ) x = rs;
- else if(rs == ) x = ls;
- else{
- if(node[ls].pri <node[rs].pri) rotL(x),erase(ls,v);
- else rotR(x) , erase(rs , v);
- }
- }
- }
- push_up(x);
- }
- int getCnt(int x , int v){//从x号节点出发找到对应的子树下小于等于v的值的个数
- if(x == ) return ;
- int ans = ;
- if(node[x].val>v) ans = getCnt(ls , v);
- else if(node[x].val<v) ans = node[x].cnt+node[ls].sz+getCnt(rs , v);
- else ans = node[x].cnt+node[ls].sz;
- return ans;
- }
- }
- int n , m , h[N] , a[N] , tot;
- //树状数组部分
- #define lowbit(x) x&(-x)
- void Add(int id , int v)
- {
- for(int x=id ; x<=n ; x+=lowbit(x)){
- Treap::insert(Treap::A[x] , v);
- }
- }
- void Erase(int id , int v)
- {
- for(int x=id ; x<=n ; x+=lowbit(x)){
- Treap::erase(Treap::A[x] , v);
- }
- }
- int getSum(int p , int v)//cal 1~p区间内小于等于v的值的个数
- {
- int sum = ;
- for(int x=p ; x> ; x-=lowbit(x)){
- sum+=Treap::getCnt(Treap::A[x] , v);
- }
- return sum;
- }
- int getSumMin(int p , int v)//cal 1~p区间内小于v的值的个数
- {
- v--;//important保证等于的情况被排除
- return getSum(p , v);
- }
- int main()
- {
- // freopen("a.in" , "r" , stdin);
- scanf("%d" , &n);
- for(int i= ; i<=n ; i++){
- scanf("%d" , &h[i]);
- a[i] = h[i];
- }
- sort(a+ , a+n+);
- tot = unique(a+ , a+n+)-(a+);
- Treap::init();
- int sum = ;
- for(int i= ; i<=n ; i++){
- h[i] = lower_bound(a+ , a+tot+ , h[i])-a;
- Add(i , h[i]);
- sum+=i--getSum(i- , h[i]);
- }
- printf("%d\n" , sum);
- scanf("%d" , &m);
- while(m--){
- // for(int i=1 ; i<=n ; i++)
- // cout<<h[i]<<" ";
- // cout<<endl;
- int ai , bi;
- scanf("%d%d" , &ai , &bi);
- if(ai>bi) swap(ai , bi);
- if(h[ai]<h[bi]) sum++;
- else if(h[ai]>h[bi]) sum--;
- else{
- printf("%d\n" , sum);
- continue;
- }
- int add = ;
- if(bi-ai>){
- add += getSumMin(bi- , h[bi])-getSumMin(ai , h[bi]);
- add -= (bi-ai-)-(getSum(bi- , h[bi])-getSum(ai , h[bi]));
- add += (bi-ai-)-(getSum(bi- , h[ai])-getSum(ai , h[ai]));
- add -= getSumMin(bi- , h[ai])-getSumMin(ai , h[ai]);
- }
- sum += add;
- Erase(ai , h[ai]);
- Erase(bi , h[bi]);
- Add(ai , h[bi]);
- Add(bi , h[ai]);
- swap(h[ai] , h[bi]);
- printf("%d\n" , sum);
- }
- return ;
- }
bzoj2141 树状数组套Treap树的更多相关文章
- BZOJ - 3295 动态逆序对 (树状数组套treap)
题目链接 思路和bzoj2141差不多,不过这道题的数据更强一些,线段树套treapT了,树状数组套treap卡过~~ #include<bits/stdc++.h> using name ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- BZOJ1901 - Dynamic Rankings(树状数组套主席树)
题目大意 给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下: Q l r k 要求你查询区间[l,r]第k小的数是哪个 C i t 要求你把第i个数修改为t 题解 动态的区间第k ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】
题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树
BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...
随机推荐
- SQL-Server使用点滴(一)
前言 SQL的语法比较简单,学起来相比界面UI控制要简单得多,但是SQL在企业级应用中又是如此的重要,以至于很多开发人员都把重点放在SQL上. SQL并没有面向对象的概念,最复杂的设计也不过是表值函数 ...
- 在SQL SERVER中获取表中的第二条数据
在SQL SERVER中获取表中的第二条数据, 思路:先根据时间逆排序取出前2条数据作为一个临时表,再按顺时排序在临时表中取出第一条数据 sql语句如下: select top 1 * from(se ...
- 移动端页面 弹出框滚动,底部body锁定,不滚动 / 微信网页禁止回弹效果
需求:页面有弹出层菜单,当弹出层菜单超出屏幕可视区域时,不能滚动.加上滚动后,底部body的滚动事件如何禁止,加上了overflow:hidden;还是不可用. 如下图:地区弹出框可以滚动,而底部的b ...
- angularjs指令系统系列课程(3):替换replace,内容保留transclude,作用方式restrict
这一节我们主要看一下replace,transclude,restrict这三个参数 1.replace 可取值:bool 默认为:true 对于replace属性,设置为false表示原有指令标识不 ...
- 如何正确使用$_SERVER['DOCUMENT_ROOT']识别该路径的文件
echo $_SERVER['DOCUMENT_ROOT']; 这时输出当前文件所在的路径 D:/phpStudy/WWW/study/php&mysql $_SERVER['DOCUMENT ...
- 团队作业week14
0 如果你的团队来了一个新队员,有一台全新的机器,你们是否有一个文档,只要设置了相应的权限,她就可以根据文档,从头开始搭建环境, 并成功地把最新.最稳定版本的软件编译出来,并运行必要的单元测试?(在这 ...
- js_多个引号的用法
str += "<input id='sel_DayB' width='120' onfocus=\"WdatePicker({skin:'whyGreen',dateFmt ...
- Opentaps安装小记
这周了解了个MES项目需求,于是乎找了些开源项目了解下,有php+mysql写的weberp,配置起来相当方便,下一版webERP_v4.13,往F:\Apache\htdocs\一放,启动F:\Ap ...
- 冰球项目日志3-yjw
小组讨论 今天大家讨论了之前各自想的方案的问题,基本确定了寻找击球点的方案,以及击球手运动轨迹规划的方案,这里我只是简单的说下我们的击球点的确定方案. 击球策略方案 方案分析 首先我们建立平面在直角坐 ...
- ubuntu16.04安装jdk,tomcat
ubuntu16.04安装jdk,tomcat 最近装了一下tomcat,网上的教程很多,我也试了很多次,但是有一些教程关于tomcat配置是错误的,让我走上了歧途.差点重装系统,还好王总及时出手帮助 ...