P3157 [CQOI2011]动态逆序对(CDQ分治)
时间:2019-11-30
本文章向大家介绍P3157 [CQOI2011]动态逆序对(CDQ分治),主要包括P3157 [CQOI2011]动态逆序对(CDQ分治)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
输入格式
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
输出格式
输出包含m行,依次为删除每个元素之前,逆序对的个数。
输入输出样例
输入 #1
5 4 1 5 3 4 2 5 1 4 2
输出 #1
5 2 2 1 样例解释 (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
说明/提示
N<=100000 M<=50000
题解: 对于一个逆序对,加一个时间维,越往后删除的时间戳越小,没有删除的值的时间戳为0,这题就变成了一个三维偏序.
我们把时间看作第一维, 从小到大排序, (j,i)作为一个逆序对出现, 则j的时间戳必定小于i的时间戳.
那么有两种情况, Tj < Ti, Pj < Pi, Vj > Vi or Tj < Ti, Pj > Pi, Vj < Vi ( T代表时间,P代表位置,V代表值)
分情况处理即可.
由于我们处理的是每个时间戳所增加的逆序对,所以我们要求一个前缀和,然后倒序输出即可.
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 200010; ll c[maxn]; int n,m; int lowbit(int x){return x & (-x);} void add(int pos,int x){ for(int i = pos;i <= n;i += lowbit(i)){ c[i] += x; } } ll query(int pos){ ll sum = 0; for(int i = pos; i >= 1;i -= lowbit(i)){ sum += c[i]; } return sum; } struct node{ int tim,pos,val; }a[maxn]; int cmp1(node a,node b){//按照时间排序 if(a.tim == b.tim)return a.pos < b.pos; return a.tim < b.tim; } int cmp2(node a,node b){//按照位置从小到大排序 return a.pos < b.pos; } int cmp3(node a,node b){//按照位置从大到小排序 return a.pos > b.pos; } ll pos[maxn],ans[maxn]; void cdq(int l,int r){ if(l == r)return ; int mid = (l + r) / 2; cdq(l,mid),cdq(mid+1,r); int i = mid + 1,j = l;//这里按照第二维 位置从小到大排序,对于右边区间的每一个点i,查询满足 pos(j) < pos(i) && val(j) > val(i)的j有多少个 sort(a + l,a + mid + 1,cmp2); sort(a + mid + 1,a + r + 1,cmp2); for(;i <= r;i++){ while(a[j].pos <= a[i].pos && j <= mid){ add(a[j].val,1); j++; } ans[a[i].tim] += query(n) - query(a[i].val); } for(int i = l;i < j;i++)add(a[i].val,-1);//清空树状数组 i = mid + 1,j = l;//这里按照第二维 位置从大到小排序,对于右边区间的每一个点i,查询满足 pos(j) > pos(i) && val(j) < val(i)的j有多少个 sort(a + l,a + mid + 1,cmp3); sort(a + mid + 1,a + r + 1,cmp3); for(;i <= r;i++){ while(a[j].pos >= a[i].pos && j <= mid){ add(a[j].val,1); j++; } ans[a[i].tim] += query(a[i].val); } for(int i = l;i < j;i++)add(a[i].val,-1);//清空树状数组 } int main() { cin >> n >> m; for(int i = 1;i <= n;i++){ cin >> a[i].val; a[i].tim = 0; pos[a[i].val] = i;//记录每个值的位置 a[i].pos = i; } for(int i = 1;i <= m;i++){ int x; cin >> x; a[pos[x]].tim = m - i + 1;//时间戳更新 } sort(a+1,a+1+n,cmp1); cdq(1,n); for(int i = 1;i <= m;i++)ans[i] += ans[i-1]; for(int i = m;i >= 1;i--)cout << ans[i] << endl; return 0; }
原文地址:https://www.cnblogs.com/cherish-lin/p/11963823.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 设计模式之工厂模式
- Solr在分布式环境中的应用
- Docker基础与实战,看这一篇就够了
- org.springframework.beans.factory.NoSuchBeanDefinitionException:
- Vector 源码剖析
- java.util.concurrent.TimeoutException: 的解决!
- HTTP Status 503 - Server is shutting down or failed to initialize
- LinkedHashMap 源码剖析
- 基于SSM框架与Maven的CRUD案例
- Java 8的这个新特性,你用了吗?
- JSP+Servlet项目整合
- springboot 整合 Mybatis、JPA、Redis
- 数据库中设置列/字段自增(Oracle和Mysql)
- 数据库中日期的插入(Oracle和Mysql)
- 浅谈在进行jsp页面编程时,路径问题的解决(绝对路径与相对路径)