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\)倍祖先的一整子树删 ...
随机推荐
- Conda 为什么越来越慢?
作者:生信宝典 | 生信宝典公众号原文:https://mp.weixin.qq.com/s/OkOgN4j44MHNt1_noPVpzA Conda 为什么越来越慢? Conda 中包含的软件越来越 ...
- flutter dio自定义http client
final dio = Dio(); Dio getMyDio() { initAdapter(); dio.options.headers = {'apiKey': 'xxxxx'}; dio.op ...
- 华为云新一代分布式数据库GaussDB,给世界一个更优选择
摘要:与伙伴一起,共建繁荣开放的GaussDB数据库新生态. 本文分享自华为云社区<华为云新一代分布式数据库GaussDB,给世界一个更优选择>,作者:华为云头条. 6月7日,在华为全球智 ...
- 【接口测试】Postman(三)-变量与集合
变量与集合 在Postman中,我们进行接口测试一般是以集合为单位,而在日常应用中,我们会经常使用到变量.下面我们将介绍一下变量和集合的一些用法. 文章目录导航: 目录 变量与集合 一.变量 1. ...
- 前端Vue自定义顶部搜索框 热门搜索 历史搜索 用于搜索跳转使用
前端Vue自定义顶部搜索框 热门搜索 历史搜索 用于搜索跳转使用, 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13128 效 ...
- 使用CosmosDB进行大规模数据的实时数据处理和流式传输
目录 使用 Cosmos DB 进行大规模数据的实时数据处理和流式传输 背景介绍 文章目的 目标受众 技术原理及概念 基本概念解释 技术原理介绍 相关技术比较 实现步骤与流程 准备工作:环境配置与依赖 ...
- redis集群报错:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.
之前在x86架构的服务器部署redis集群,未遇到题中问题:然而在ARM架构的服务器部署redis集群,第一次遇到如此问题.虽然问题已经解决,但不清楚问题的具体原因,在此做个记录. 性能测试过程中,通 ...
- 怎么把 session 中的实体类转换回来
例子 : 如上比如user user1=new user(): user1.id=1: user1.name="张三": session["user1"]=us ...
- 【转载】Linux虚拟化KVM-Qemu分析(一)
原文信息 作者:LoyenWang 出处:https://www.cnblogs.com/LoyenWang/ 公众号:LoyenWang 版权:本文版权归作者和博客园共有 转载:欢迎转载,但未经作者 ...
- docker部署zabbix6.0及企业微信发送告警
1 前言 1.1 实验背景 因zabbix 6.0新增许多新特性,为熟悉界面特意在本地部署一套简易版(未启用HA功能).原本想要在烧制了centos7.9系统树莓派上部署,一查之下armv7果然冷门, ...