嘛,好久没碰CDQ分治了,做道题练练手。

时间倒流——把删数改为加数。

对于每个被删的,我的想法是拆成询问和add,后来发现一个足矣。

我本来准备对每个删的数都求一遍整体逆序对,后来发现无论如何都不可做。

然后发现是只求改的逆序对,做两次CDQ,一次统计在前面大的,一次统计在后面小的。

注意:这两次的区别是id那一维的顺序不同,而time顺序是相同的。

记得离散化。

然后我打完 + 静态差错之后,一发过样例AC,稳!!!

顺手切了一模一样的3157,WA了两个点。发现输出负数......换成longlong之后AC。

 #include <cstdio>
#include <algorithm>
#include <cstring> typedef long long LL; const LL N = ; LL x[N], a[N], n; struct TreeArray {
LL tr[N];
inline void clear() {
memset(tr, , sizeof(tr));
return;
}
inline void add(LL x, LL a) {
for(; x < N; x += x & (-x)) {
tr[x] += a;
}
return;
}
inline LL getsum(LL x) {
LL ans = ;
for(; x; x -= x & (-x)) {
ans += tr[x];
}
return ans;
}
inline LL ask(LL l, LL r) {
if(l == ) {
return getsum(r);
}
return getsum(r) - getsum(l - );
}
}ta; struct Node {
LL val, ans, time, type, id;
}node[N], temp[N]; inline bool cmp_t(Node d, Node e) {
return d.time < e.time;
}
inline bool cmp__t(Node d, Node e) {
return d.time > e.time;
} void CDQ1(LL l, LL r) {
if(l == r) {
return;
}
LL mid = (l + r) >> ;
CDQ1(l, mid);
CDQ1(mid + , r); LL i = l, j = mid + , t = ;
while(i <= mid || j <= r) {
if(j > r || (i <= mid && node[i].id < node[j].id)) {
ta.add(node[i].val, );
temp[++t] = node[i++];
}
else {
if(node[j].type == ) {
node[j].ans += ta.ask(node[j].val + , n);
}
temp[++t] = node[j++];
}
}
for(i = l; i <= mid; i++) {
ta.add(node[i].val, -);
}
t = ;
for(LL i = l; i <= r; i++) {
node[i] = temp[++t];
}
return;
} void CDQ2(LL l, LL r) {
if(l == r) {
return;
}
LL mid = (l + r) >> ;
CDQ2(l, mid);
CDQ2(mid + , r); LL i = l, j = mid + , t = ;
while(i <= mid || j <= r) {
if(j > r || (i <= mid && node[i].id > node[j].id)) { /// error : id < id
ta.add(node[i].val, 1);/// error : if(type == 1)
temp[++t] = node[i++];
}
else {
if(node[j].type == ) {
node[j].ans += ta.getsum(node[j].val - );
}
temp[++t] = node[j++];
}
}
for(i = l; i <= mid; i++) {
ta.add(node[i].val, -);/// error : if(type == 1)
}
t = ;
for(i = l; i <= r; i++) {
node[i] = temp[++t];
}
return;
} LL pos[N]; int main() {
LL m;
scanf("%lld%lld", &n, &m);
for(LL i = ; i <= n; i++) {
scanf("%lld", &a[i]);
x[i] = a[i];
node[i].id = i;
node[i].type = ; /// normal
}
std::sort(x + , x + n + );
LL xx = std::unique(x + , x + n + ) - x - ;
for(LL i = ; i <= n; i++) {
LL p = std::lower_bound(x + , x + xx + , a[i]) - x;
node[i].val = p;
pos[p] = i;
}
/// li san hua wan bi LL nn = n, p;
for(LL i = ; i <= m; i++) {
scanf("%lld", &p);
p = std::lower_bound(x + , x + xx + , p) - x;
p = pos[p];
node[p].type = ; /// add
node[p].time = nn--;
}
for(LL i = ; i <= n; i++) {
if(node[i].type == ) {
node[i].time = nn--;
}
}
LL ans = ;
for(LL i = ; i <= n; i++) {
if(node[i].type == ) {
ans += ta.ask(node[i].val + , n);
ta.add(node[i].val, );
}
}
ta.clear();
std::sort(node + , node + n + , cmp_t);
CDQ1(, n);
std::sort(node + , node + n + , cmp_t); /// error : cmp__t -> cmp_t
CDQ2(, n);
std::sort(node + , node + n + , cmp__t);
for(LL i = ; i <= m; i++) {
ans += node[i].ans;
}
for(LL i = ; i <= m; i++) {
printf("%lld\n", ans);
ans -= node[i].ans;
}
return ;
}

P3157

 #include <cstdio>
#include <algorithm>
#include <cstring> const int N = ; int x[N], a[N], n; struct TreeArray {
int tr[N];
inline void clear() {
memset(tr, , sizeof(tr));
return;
}
inline void add(int x, int a) {
for(; x < N; x += x & (-x)) {
tr[x] += a;
}
return;
}
inline int getsum(int x) {
int ans = ;
for(; x; x -= x & (-x)) {
ans += tr[x];
}
return ans;
}
inline int ask(int l, int r) {
if(l == ) {
return getsum(r);
}
return getsum(r) - getsum(l - );
}
}ta; struct Node {
int val, ans, time, type, id;
}node[N], temp[N]; inline bool cmp_t(Node d, Node e) {
return d.time < e.time;
}
inline bool cmp__t(Node d, Node e) {
return d.time > e.time;
} void CDQ1(int l, int r) {
if(l == r) {
return;
}
int mid = (l + r) >> ;
CDQ1(l, mid);
CDQ1(mid + , r); int i = l, j = mid + , t = ;
while(i <= mid || j <= r) {
if(j > r || (i <= mid && node[i].id < node[j].id)) {
ta.add(node[i].val, );
temp[++t] = node[i++];
}
else {
if(node[j].type == ) {
node[j].ans += ta.ask(node[j].val + , n);
}
temp[++t] = node[j++];
}
}
for(i = l; i <= mid; i++) {
ta.add(node[i].val, -);
}
t = ;
for(int i = l; i <= r; i++) {
node[i] = temp[++t];
}
return;
} void CDQ2(int l, int r) {
if(l == r) {
return;
}
int mid = (l + r) >> ;
CDQ2(l, mid);
CDQ2(mid + , r); int i = l, j = mid + , t = ;
while(i <= mid || j <= r) {
if(j > r || (i <= mid && node[i].id > node[j].id)) {
ta.add(node[i].val, );
temp[++t] = node[i++];
}
else {
if(node[j].type == ) {
node[j].ans += ta.getsum(node[j].val - );
}
temp[++t] = node[j++];
}
}
for(i = l; i <= mid; i++) {
ta.add(node[i].val, -);
}
t = ;
for(i = l; i <= r; i++) {
node[i] = temp[++t];
}
return;
} int main() {
int m;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
x[i] = a[i];
node[i].id = i;
node[i].type = ; /// normal
}
std::sort(x + , x + n + );
int xx = std::unique(x + , x + n + ) - x - ;
for(int i = ; i <= n; i++) {
int p = std::lower_bound(x + , x + xx + , a[i]) - x;
node[i].val = p;
}
/// li san hua wan bi int nn = n;
for(int i = ; i <= m; i++) {
scanf("%d", &xx);
node[xx].type = ; /// add
node[xx].time = nn--;
}
for(int i = ; i <= n; i++) {
if(node[i].type == ) {
node[i].time = nn--;
}
}
int ans = ;
for(int i = ; i <= n; i++) {
if(node[i].type == ) {
ans += ta.ask(node[i].val + , n);
ta.add(node[i].val, );
}
}
ta.clear();
std::sort(node + , node + n + , cmp_t);
CDQ1(, n);
std::sort(node + , node + n + , cmp_t);
CDQ2(, n);
std::sort(node + , node + n + , cmp__t);
for(int i = ; i <= m; i++) {
ans += node[i].ans;
}
for(int i = ; i <= m + ; i++) {
printf("%d ", ans);
ans -= node[i].ans;
}
return ;
}

P1393

CDQ大法好!

洛谷 P1393 P3157 动态逆序对的更多相关文章

  1. P3157 动态逆序对 CDQ分治

    动态逆序对 CDQ分治 传送门:https://www.luogu.org/problemnew/show/P3157 题意: 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对 ...

  2. 洛谷P3157 动态逆序对 [CQOI2011] cdq分治

    正解:cdq分治 解题报告: 传送门! 长得有点像双倍经验还麻油仔细看先放上来QwQ! 这题首先想到的就直接做逆序对,然后记录每个点的贡献,删去就减掉就好 但是仔细一想会发现布星啊,如果有一对逆序对的 ...

  3. 【洛谷 P2513】 [HAOI2009]逆序对数列(DP)

    题目链接 这种求方案数的题一般都是\(dp\)吧. 注意到范围里\(k\)和\(n\)的范围一样大,\(k\)是完全可以更大的,到\(n\)的平方级别,所以这暗示了我们要把\(k\)写到状态里. \( ...

  4. 洛谷 P4280 bzoj1786 [AHOI2008]逆序对(dp)

    题面 luogu bzoj 题目大意: 给你一个长度为\(n\)的序列,元素都在\(1-k\)之间,有些是\(-1\),让你把\(-1\)也变成\(1-k\)之间的数,使得逆序对最多,求逆序对最少是多 ...

  5. 洛谷P1966 火柴排队(逆序对)

    题意 题目链接 Sol 不算很难的一道题 首先要保证权值最小,不难想到一种贪心策略,即把两个序列中rank相同的数放到同一个位置 证明也比较trivial.假设\(A\)中有两个元素\(a, b\), ...

  6. 洛谷【P1908】逆序对

    题目传送门:https://www.luogu.org/problemnew/show/P1908 所谓逆序对,就是序列中\(a[i]>a[j]\)且\(i<j\)的有序对. 所以我们在归 ...

  7. 【Luogu】P3157动态逆序对(树状数组套主席树)

    题目链接 md第一道在NOILinux 下用vim做的紫题.由于我对这个操作系统不是很熟悉,似乎有什么地方搞错了,md调死.(我还打了两遍代码,调了两个小时) 但是这道题并不难,就是树状数组套上主席树 ...

  8. 洛谷 题解 P1908 【逆序对】

    一开始竟然妄想用\(n^2\)的算法过这题,然而这是不可能的 所以只好写归并排序来求逆序対惹 比如将下面两个区间排序 3 4 7 9 1 5 8 10 首先将右区间的\(1\)取出,放到\(r_k\) ...

  9. bzoj3295 洛谷P3157、1393 动态逆序对——树套树

    题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295 洛谷 P3157(同一道题) https://www.luogu.o ...

随机推荐

  1. Git使用:Linux(Ubuntu 14.04 x64)下安装Git并配置连接GitHub

    github是一个非常好的网络代码托管仓库,知晓许久,但是一直没有用起来,最近才开始使用git管理自己的文档和代码. Git是非常强大的版本管理工具,今天就告诉大家,如何在Linux下安装GIt,并且 ...

  2. idea的pom.xml中提示dependency‘’not found

    今天下午在更新svn上的项目到本地,发现pom文件中的如下依赖的version一直标红,鼠标放上去显示“dependency not found.” 同时检查了Maven Projects中该项目引入 ...

  3. Helm

    helm类似yum helm下载的是配置清单文件 核心术语: Chart:一个helm程序包: Repository:Charts仓库,https/http服务器: Release:特定的Chart部 ...

  4. 插件 DataTable 创建列表 render参数的详解与如何传递本行数据id

    1.首先 导入DataTable 的插件 2.定义表结构: HTML: <table> <thead> <tr> <th>id</th> & ...

  5. 初识Xml。

    /* * 一.Xml? * * 1.是什么? * Extensible markup Language 可拓展标记性语言 * 功能是 储存数据 * 1.配置文件 * 2.在网络中传输数据 * xml和 ...

  6. js函数使用prototype和不适用prototype的区别

    js中类定义函数时用prototype与不用的区别 原创 2017年06月05日 12:25:41 标签: 函数 / prototype / class   首先来看一个实例: function Li ...

  7. DotNetty 实现 Modbus TCP 系列 (二) ModbusFunction 类图及继承举例

    本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 ModbusFunction 类图如下: 如前文所述,所有请求/相应的 PDU 均继承自 ModbusFunction, ...

  8. oss命令使用

    下载文件夹 ossutil64 cp oss://folder/ out_folder/ -r --jobs 20

  9. 当对具体的一条记录进行操作时候 需要传递该记录的id

  10. vuex2.0 基本使用(3) --- getter

    有的组件中获取到 store 中的state,  需要对进行加工才能使用,computed 属性中就需要写操作函数,如果有多个组件中都需要进行这个操作,那么在各个组件中都写相同的函数,那就非常麻烦,这 ...