Solution -「洛谷 P5046」「YunoOI 2019 模拟赛」Yuno loves sqrt technology I
Description
Link.
无修改区间求逆序对。
Solution
首先有一个显然的 \(\Theta(N\sqrt{N}\log_{2}N)\) 做法,由于过不了所以我就不废话。
其实有了 \(\Theta(N\sqrt{N}\log_{2}N)\) 的过不去做法,我们就可以根据这个思路然后预处理解决问题。
我们需要处理的信息有:
散块的逆序对数量
以块为单位的区间逆序对数量
那么我们需要处理的数组就有以下几个:
previous[i]表示 \(i\) 到 该块开头的逆序对数量。suffix[i]同理。block[i][j]表示前 \(i\) 个块中 \(\leq j\) 元素个数。intervals[i][j]表示以块为单位的区间 \([i,j]\) 中的逆序对数量。
讲讲预处理方法。
previous[i]和suffix[i]的处理方法都很显然,可以一直扫着然后FWT扫就行。block[i][j]可以递推,递推式为block[i][j]=block[i+1][j]+block[i][j-1]-block[i+1][j-1]+cont(i,j)。其中cont(i,j)表示计算对应块的逆序对数。intervals[i][j]每次循环到块的开头继承上一个块的贡献即可。
计算贡献的方法很简单,归并即可。mrsrz讲得也挺清楚的,我这里就不再赘述,主要讲讲怎么卡常。
首先我们可以把主函数里的所有循环全部展开,经过实践参数传8的时候跑得比较快。
然后八聚氧先加上,luogu O2也开着。
再其次快读fread快输fwrite,这些都是卡常的标配。
然后就把能拿出来的结构体拿出来,实在不能就不管了。
然后去STL,pair vector能去就去。
然后long long开在正确的地方,不要无脑replace。
函数inline,循环register。虽然可能作用不大但是可以先加上。
然后调块长,经过无数次实践发现取150~170较为优秀。
然后加了过后发现就算rp再好也只有60pts。
然后谷歌搜索硫酸的化学式H₂SO₄,给评测机喂硫酸(idea来自SyadouHayami)。
然后本来交了5页都过不了,这下再交两次就过了。
// 省略八聚氧
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int Maxn = 1e5 + 5;
const int Maxm = 650;
const int each = 160;
int n, m, blocks, Lp[Maxn], Rp[Maxn], isa[Maxn], head[Maxn], tail[Maxn], sorted[Maxn], belong[Maxn], previous[Maxn], suffix[Maxn], block[Maxm][Maxn];
long long intervals[Maxm][Maxn];
struct Holy_Pair
{
int first, second;
bool operator < (const Holy_Pair& rhs) const
{
return first < rhs.first;
}
} current[Maxn];
struct Fenwick_Tree
{
int fwt[Maxn];
inline void Modify(int x, int v)
{
for (; x + 5 <= Maxn; x += x & -x) fwt[x] += v;
}
inline int Query(int x)
{
int ret = 0;
for (; x; x ^= x & -x) ret += fwt[x];
return ret;
}
} FWT;
#define io_e '\0'
#define io_s ' '
#define io_l '\n'
namespace Fast_IO
{
... // 省略快读
} // namespace Fast_IO
using Fast_IO::read;
using Fast_IO::write;
inline Holy_Pair make_pair(int first, int second)
{
Holy_Pair ret;
ret.first = first;
ret.second = second;
return ret;
}
inline int Merge_Vct(int rhs[], int shr[], int szl, int szr)
{
int itl = 1, itr = 1;
int ret = 0, ctr = 1;
while (itl <= szl && itr <= szr)
{
if (rhs[itl] < shr[itr]) ++itl, ++ctr;
else
{
ret += szl - ctr + 1;
++itr;
}
}
return ret + szr - szr;
}
inline int Merge_Idx(int st1, int st2, int sz1, int sz2)
{
int ret = 0, id1 = st1 + 1, id2 = st2 + 1;
sz1 += st1, sz2 += st2;
while (id1 <= sz1 && id2 <= sz2)
{
if (sorted[id1] < sorted[id2]) ++id1;
else
{
ret += sz1 - id1 + 1;
++id2;
}
}
return ret;
}
inline void Behavior(int l, int r, long long &ans)
{
int itl = 0, itr = 0;
if (belong[l] == belong[r])
{
for (int i = head[belong[l]]; i <= tail[belong[r]]; ++i)
{
if (current[i].second >= l && current[i].second <= r) Rp[++itr] = sorted[i];
else if (current[i].second < l) Lp[++itl] = sorted[i];
}
if (l == head[belong[l]]) ans = previous[r] - Merge_Vct(Lp, Rp, itl, itr);
else ans = previous[r] - previous[l - 1] - Merge_Vct(Lp, Rp, itl, itr);
}
else
{
ans = intervals[belong[l] + 1][belong[r] - 1] + previous[r] + suffix[l];
for (int i = head[belong[l]]; i <= tail[belong[l]]; ++i)
{
if (current[i].second >= l)
{
Lp[++itl] = sorted[i];
ans += block[belong[r] - 1][1] - block[belong[r] - 1][sorted[i]] - block[belong[l]][1] + block[belong[l]][sorted[i]];
}
}
for (int i = head[belong[r]]; i <= tail[belong[r]]; ++i)
{
if (current[i].second <= r)
{
Rp[++itr] = sorted[i];
ans += block[belong[r] - 1][sorted[i] + 1] - block[belong[l]][sorted[i] + 1];
}
}
ans += Merge_Vct(Lp, Rp, itl, itr);
}
write(io_l, ans);
}
signed main()
{
read(n, m), blocks = (n - 1) / each + 1;
if (n <= 8)
{
for (int i = 1; i <= n; ++i)
{
read(isa[i]);
current[i] = make_pair(isa[i], i);
}
}
else
{
#pragma unroll 8
for (int i = 1; i <= n; ++i)
{
read(isa[i]);
current[i] = make_pair(isa[i], i);
}
}
if (blocks <= 8)
{
for (int i = 1; i <= blocks; ++i)
{
head[i] = tail[i - 1] + 1;
tail[i] = tail[i - 1] + each;
if (i == blocks) tail[i] = n;
}
}
else
{
#pragma unroll 8
for (int i = 1; i <= blocks; ++i)
{
head[i] = tail[i - 1] + 1;
tail[i] = tail[i - 1] + each;
if (i == blocks) tail[i] = n;
}
}
if (blocks <= 8)
{
for (int i = 1; i <= blocks; ++i)
{
memcpy(block[i], block[i - 1], sizeof(block[0]));
sort(current + head[i], current + 1 + tail[i]);
for (int j = head[i]; j <= tail[i]; ++j)
{
++block[i][isa[j]];
belong[j] = i;
sorted[j] = current[j].first;
}
int satisfy = 0;
for (int j = head[i]; j <= tail[i]; ++j)
{
FWT.Modify(isa[j], 1);
satisfy += FWT.Query(n) - FWT.Query(isa[j]);
previous[j] = satisfy;
}
intervals[i][i] = satisfy;
for (int j = head[i]; j <= tail[i]; ++j)
{
suffix[j] = satisfy;
FWT.Modify(isa[j], -1);
satisfy -= FWT.Query(isa[j] - 1);
}
}
}
else
{
#pragma unroll 8
for (int i = 1; i <= blocks; ++i)
{
memcpy(block[i], block[i - 1], sizeof(block[0]));
sort(current + head[i], current + 1 + tail[i]);
for (int j = head[i]; j <= tail[i]; ++j)
{
++block[i][isa[j]];
belong[j] = i;
sorted[j] = current[j].first;
}
int satisfy = 0;
for (int j = head[i]; j <= tail[i]; ++j)
{
FWT.Modify(isa[j], 1);
satisfy += FWT.Query(n) - FWT.Query(isa[j]);
previous[j] = satisfy;
}
intervals[i][i] = satisfy;
for (int j = head[i]; j <= tail[i]; ++j)
{
suffix[j] = satisfy;
FWT.Modify(isa[j], -1);
satisfy -= FWT.Query(isa[j] - 1);
}
}
}
if (blocks <= 8)
{
for (int dis = 1; dis <= blocks; ++dis)
{
for (int i = n - 1; i; --i) block[dis][i] += block[dis][i + 1];
for (int l = 1, r = dis + 1; r <= blocks + 1; ++l, ++r)
intervals[l][r] = intervals[l + 1][r] + intervals[l][r - 1] - intervals[l + 1][r - 1] +
Merge_Idx(head[l] - 1, head[r] - 1, tail[l] - head[l] + 1, tail[r] - head[r] + 1);
}
}
else
{
#pragma unroll 8
for (int dis = 1; dis <= blocks; ++dis)
{
for (int i = n - 1; i; --i) block[dis][i] += block[dis][i + 1];
for (int l = 1, r = dis + 1; r <= blocks + 1; ++l, ++r)
intervals[l][r] = intervals[l + 1][r] + intervals[l][r - 1] - intervals[l + 1][r - 1] +
Merge_Idx(head[l] - 1, head[r] - 1, tail[l] - head[l] + 1, tail[r] - head[r] + 1);
}
}
if (m <= 8)
{
long long lastans = 0;
for (int i = 0; i < m; ++i)
{
long long l, r;
read(l, r);
l ^= lastans;
r ^= lastans;
Behavior(l, r, lastans);
}
}
else
{
long long lastans = 0;
#pragma unroll 8
for (int i = 0; i < m; ++i)
{
long long l, r;
read(l, r);
l ^= lastans;
r ^= lastans;
Behavior(l, r, lastans);
}
}
return 0;
}
Solution -「洛谷 P5046」「YunoOI 2019 模拟赛」Yuno loves sqrt technology I的更多相关文章
- 洛谷 P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I(分块+卡常)
洛谷题面传送门 zszz,lxl 出的 DS 都是卡常题( 首先由于此题强制在线,因此考虑分块,我们那么待查询区间 \([l,r]\) 可以很自然地被分为三个部分: 左散块 中间的整块 右散块 那么这 ...
- [洛谷P5048][Ynoi2019模拟赛]Yuno loves sqrt technology III
题目大意:有$n(n\leqslant5\times10^5)$个数,$m(m\leqslant5\times10^5)$个询问,每个询问问区间$[l,r]$中众数的出现次数 题解:分块,设块大小为$ ...
- 洛谷P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III(分块)
传送门 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 用蒲公英那个分块的方法做结果两天没卡过去→_→ 首先我们分块,预处理块与块之间的答案,然后每次询问的时候拆成整块和两边剩下的元素 整块的答案很简 ...
- 洛谷 P5048 - [Ynoi2019 模拟赛] Yuno loves sqrt technology III(分块)
题面传送门 qwq 感觉跟很多年前做过的一道题思路差不多罢,结果我竟然没想起那道题?!!所以说我 wtcl/wq 首先将 \(a_i\) 离散化. 如果允许离线那显然一遍莫队就能解决,复杂度 \(n\ ...
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- 「 洛谷 」P2768 珍珠项链
珍珠项链 题目限制 内存限制:125.00MB 时间限制:1.00s 标准输入输出 题目知识点 动态规划 \(dp\) 矩阵 矩阵乘法 矩阵加速 矩阵快速幂 题目来源 「 洛谷 」P2768 珍珠项链 ...
- 「 洛谷 」P4539 [SCOI2006]zh_tree
小兔的话 推荐 小兔的CSDN [SCOI2006]zh_tree 题目限制 内存限制:250.00MB 时间限制:1.00s 标准输入输出 题目知识点 思维 动态规划 \(dp\) 区间\(dp\) ...
- 「 洛谷 」P2151 [SDOI2009]HH去散步
小兔的话 欢迎大家在评论区留言哦~ HH去散步 题目限制 内存限制:125.00MB 时间限制:1.00s 标准输入 标准输出 题目知识点 动态规划 \(dp\) 矩阵 矩阵乘法 矩阵加速 矩阵快速幂 ...
- 「CSP-S模拟赛」2019第四场
「CSP-S模拟赛」2019第四场 T1 「JOI 2014 Final」JOI 徽章 题目 考场思考(正解) T2 「JOI 2015 Final」分蛋糕 2 题目 考场思考(正解) T3 「CQO ...
- #10471. 「2020-10-02 提高模拟赛」灌溉 (water)
题面:#10471. 「2020-10-02 提高模拟赛」灌溉 (water) 假设只有一组询问,我们可以用二分求解:二分最大距离是多少,然后找到深度最大的结点,并且把它的\(k\)倍祖先的一整子树删 ...
随机推荐
- 曲线艺术编程 coding curves 第四章 利萨茹曲线(Lissajous Curves)
第四章 利萨茹曲线(Lissajous Curves) 原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ 译者:池 ...
- 【LeetCode.384打乱数组】Knuth洗牌算法详解
前两天看网易面筋得知网易云的随机歌曲播放使用了这个算法,遂找题来做做学习一下 打乱数组 https://leetcode.cn/problems/shuffle-an-array/ 给你一个整数数组 ...
- java匿名内部类的初解
java原生态中的匿名内部类 1.匿名内部类的定义 使用匿名内部类的两种的方法 建立父类,重写父类的方法 实现接口的方法 2.普通类的实现 1. 普通类实现 实现普通类需要先声明对一个类的对象,再调用 ...
- 聊聊Zookeeper的Session会话超时重连
概述 简单地说,ZooKeeper的连接与会话就是客户端通过实例化ZooKeeper对象来实现客户端与服务器创建并保持TCP连接的过程.本质上,Session就是一个TCP 长连接. 会话 Sessi ...
- 轻松掌握Python+主流测试框架Requests接口自动化,快速转型自动化测试
轻松掌握Python+主流测试框架Requests接口自动化,快速转型自动化测试 最近几年,自动化测试已经成为了软件测试的主流趋势,而Python语言和Requests库作为主流测试框架,也成为了越来 ...
- 如何通过AWS的云安全服务保护企业数据
目录 随着企业数字化程度的不断加深,数据安全和隐私保护成为了企业面临的新的挑战.在数字化转型的过程中,企业需要处理大量的数据,这些数据的安全性和隐私保护的重要性不言而喻. AWS 云安全服务是Amaz ...
- Zabbix Timeout 设置不当导致的问题
哈喽大家好,我是咸鱼 今天跟大家分享一个关于 zabbix Timeout 值设置不当导致的问题,这个问题不知道大家有没有碰到过 问题 事情经过是这样的: 把某一台 zabbix agent 的模板由 ...
- 2023-07-05:爱丽丝和鲍勃继续他们的石子游戏 许多堆石子 排成一行,每堆都有正整数颗石子 piles[i] 游戏以谁手中的石子最多来决出胜负。 爱丽丝和鲍勃轮流进行,爱丽丝先开始。最初,
2023-07-05:爱丽丝和鲍勃继续他们的石子游戏 许多堆石子 排成一行,每堆都有正整数颗石子 piles[i] 游戏以谁手中的石子最多来决出胜负. 爱丽丝和鲍勃轮流进行,爱丽丝先开始.最初,M = ...
- C#.NET Framework 使用BC库(BouncyCastle) RSA 公钥加密 私钥解密 ver:20230706
C#.NET Framework 使用BC库(BouncyCastle) RSA 公钥加密 私钥解密 ver:20230706 环境说明: .NET Framework 4.6 的控制台程序 . 20 ...
- 4.6 x64dbg 内存扫描与查壳实现
LyScript 插件中默认提供了多种内存特征扫描函数,每一种扫描函数用法各不相同,在使用扫描函数时应首先搞清楚不同函数之间的差异,本章内容将分别详细介绍每一种内存扫描函数是如何灵活运用,并实现一种内 ...