【2019.8.8 慈溪模拟赛 T2】query(query)(分治+分类讨论)
分治
首先,我们考虑分治处理此问题。
每次处理区间\([l,r]\)时,我们先处理完\([l,mid]\)和\([mid+1,r]\)两个区间的答案,然后我们再考虑计算左区间与右区间之间的答案。
处理的时候就需要分类讨论。
分类讨论
设\(Mn_x\)在\(l\le x\le mid\)时表示左区间的后缀最小值,\(mid+1\le x\le r\)时表示右区间的前缀最小值;\(Mx_x\)同理根据\(x\)的取值范围分别表示左区间的后缀最大值和右区间的前缀最大值。
考虑在左区间枚举左端点\(i\),用双指针在右区间移动,把右区间划分成三部分。
第一部分,这段区间内的\(x\)满足\(Mn_x\ge Mn_i,Mx_x\le Mx_i\)。
那么当右端点取在这段区间内时,答案都取\(Mn_i\&Mx_i\)。
第二部分,这段区间内的\(x\)满足\(Mn_x\ge Mn_i,Mx_x>Mx_i\)或者\(Mn_x<Mn_i,Mx_x\le Mx_i\)。
此时最小值或最大值中的其中一个会取这段区间中的值,另一个会取\(i\)位置的值。
这里以这段区间中取最小值,\(i\)位置上取最大值为例。
那么就是将这段区间内的\(Mn_x\)全都\(\&\)上\(Mx_i\)之后再求和。
只要将每个\(Mn_x\)二进制分解一下,然后每一位求前缀和。
询问时枚举二进制下每一位,若\(Mx_i\)这一位上有值,就计入答案,否则忽略不计。
第三部分,这段区间内的\(x\)满足\(Mn_x<Mn_i,Mx_x>Mx_i\)。
这时候答案取\(Mn_x\&Mx_x\),只要预处理一下就可以了。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LV 20
#define LL long long
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
#define Gmin(x,y) (x>(y)&&(x=(y)))
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,a[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
#undef D
}F;
class DivideSolver//分治
{
private:
int Mn[N+5],Mx[N+5],Mn_[N+5][LV+5],Mx_[N+5][LV+5];LL ans,S[N+5];
I void Work(int *sl,int *sr,CI v)
{
for(RI i=0;i<=LV;++i) v>>i&1&&(ans+=(1LL<<i)*(sr[i]-sl[i]));//枚举二进制下每一位计算答案
}
I void Divide(CI l,CI r)
{
if(l>=r) return;RI i,j,mid=l+r>>1;Divide(l,mid),Divide(mid+1,r);//递归处理子区间
for(Mn[mid]=Mx[mid]=a[mid],i=mid-1;i>=l;--i)//预处理左区间后缀最小值/最大值
Mn[i]=min(a[i],Mn[i+1]),Mx[i]=max(a[i],Mx[i+1]);
for(Mn[mid+1]=Mx[mid+1]=a[mid+1],i=mid+2;i<=r;++i)//预处理右区间前缀最小值/最大值
Mn[i]=min(a[i],Mn[i-1]),Mx[i]=max(a[i],Mx[i-1]);
memset(Mn_[mid],0,sizeof(Mn_[mid])),memset(Mx_[mid],0,sizeof(Mx_[mid]));//清空
for(i=mid+1;i<=r;++i) for(j=0;j<=LV;++j)//二进制分解右区间的Mn,Mx,并求前缀和
Mn_[i][j]=Mn_[i-1][j],Mx_[i][j]=Mx_[i-1][j],
Mn[i]>>j&1&&++Mn_[i][j],Mx[i]>>j&1&&++Mx_[i][j];
for(S[mid]=0,i=mid+1;i<=r;++i) S[i]=S[i-1]+(Mx[i]&Mn[i]);//统计右区间Mn[x]&Mx[x]的和
RI pl=mid,pr=mid+1;for(i=mid;i>=l;--i)//在左区间枚举
{
W(pl<r&&Mn[pl+1]>=Mn[i]&&Mx[pl+1]<=Mx[i]) ++pl;//指针在右区间移动
W(pr<=r&&(Mn[pr]>=Mn[i]||Mx[pr]<=Mx[i])) ++pr;//指针在右区间移动
ans+=1LL*(pl-mid)*(Mn[i]&Mx[i])+S[r]-S[pr-1];if(pl+1>pr-1) continue;//计算一、三两部分答案
Mx[pl+1]>Mx[i]?Work(Mx_[pl],Mx_[pr-1],Mn[i]):Work(Mn_[pl],Mn_[pr-1],Mx[i]);//计算第二部分答案
}
}
public:
I void Solve()
{
for(RI i=1;i<=n;++i) ans+=a[i];//考虑单点答案
Divide(1,n),printf("%lld",ans);//输出答案
}
}D;
int main()
{
freopen("query.in","r",stdin),freopen("query.out","w",stdout);
RI i;for(F.read(n),i=1;i<=n;++i) F.read(a[i]);return D.Solve(),0;
}
【2019.8.8 慈溪模拟赛 T2】query(query)(分治+分类讨论)的更多相关文章
- 【2019.8.15 慈溪模拟赛 T2】组合数(binom)(卢卡斯定理+高维前缀和)
卢卡斯定理 题目中说到\(p\)是质数. 而此时要求组合数向质数取模的结果,就可以用卢卡斯定理: \[C_x^y=C_{x\ div\ p}^{y\ div\ p}\cdot C_{x\ mod\ p ...
- 【2019.8.6 慈溪模拟赛 T2】树上路径(tree)(Trie)
从暴力考虑转化题意 考虑最暴力的做法,我们枚举路径的两端,然后采用类似求树上路径长度的做法,计算两点到根的贡献,然后除去\(LCA\)到根的贡献两次. 即,设\(v_i\)为\(i\)到根路径上的边权 ...
- 【2019.8.7 慈溪模拟赛 T2】环上随机点(ran)(自然算法)
简单声明 我是蒟蒻不会推式子... 所以我用的是乱搞做法... 大自然的选择 这里我用的乱搞做法被闪指导赐名为"自然算法",对于这种输入信息很少的概率题一般都很适用. 比如此题,对 ...
- 【2019.8.9 慈溪模拟赛 T2】摘Galo(b)(树上背包)
树上背包 这应该是一道树上背包裸题吧. 众所周知,树上背包的朴素\(DP\)是\(O(nm^2)\)的. 但对于这种体积全为\(1\)的树上背包,我们可以通过记\(Size\)优化转移时的循环上界,做 ...
- 【2019.8.12 慈溪模拟赛 T2】汪哥图(wang)(前缀和)
森林 考虑到题目中给出条件两点间至多只有一条路径. 就可以发现,这是一个森林. 而森林有一个很有用的性质. 考虑对于一棵树,点数-边数=\(1\). 因此对于一个森林,点数-边数=连通块个数. 所以, ...
- 【2019.8.14 慈溪模拟赛 T2】黑心老板(gamble)(2-SAT)
\(2-SAT\) 考虑每个点只能选择\(R\)或\(B\),可以看作选\(0\)或\(1\). 然后对于给出的关系式,若其中一个位置满足关系式,另两个位置就必须不满足关系式,这样就可以对于每个关系式 ...
- 【2019.8.11下午 慈溪模拟赛 T2】数数(gcd)(分块+枚举因数)
莫比乌斯反演 考虑先推式子: \[\sum_{i=l}^r[gcd(a_i,G)=1]\] \[\sum_{i=l}^r\sum_{p|a_i,p|G}\mu(p)\] \[\sum_{p|G}\mu ...
- 【2019.8.11上午 慈溪模拟赛 T2】十七公斤重的文明(seventeen)(奇偶性讨论+动态规划)
题意转化 考虑我们对于集合中每一个\(i\),若\(i-2,i+k\)存在,就向其连边. 那么,一个合法的集合就需要满足,不会存在环. 这样问题转化到了图上,就变得具体了许多,也就更容易考虑.求解了. ...
- 【2019.8.15 慈溪模拟赛 T1】插头(plugin)(二分+贪心)
二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能 ...
随机推荐
- 去掉Oracle数据库中字段值前后空格
发现oracle字段钟包含了空格,可能是前空格,也可能是后空格,因为是历史数据,需要特殊处理.但是中间的空格可能是一些特殊人员的姓名含有,这种情况不能处理.所以我们只需要处理前后空格即可.使用如下sq ...
- JVM GC系列 — GC算法
一.前言 从本篇文章开始,将开始一个新的系列JVM.JVM是一个非常庞大且复制的技术体系,但是对于程序猿的升级,走向更高阶所必要经历的,曾经也下决心要好好学习一番,然而毅力不足都中途放弃. GC的作用 ...
- Windows 10 powershell 中文乱码解决方案
Windows 10 powershell 中文乱码解决方案 Intro 我装的系统是英文版的 win 10 操作系统,最近使用命令行测试接口,发现中文显示一直异常, 使用网上的各种解决方案都没有效果 ...
- GO 键盘输入和打印输出
键盘输入和打印输出 一.打印输出 1.1 fmt包 fmt包实现了类似C语言printf和scanf的格式化I/O.格式化verb('verb')源自C语言但更简单. 详见官网fmt的API:http ...
- Android Studio 提高开发效率的插件
好久没有更新博客了,最近搞个listview搞得半死不活的,心累~~ 今天带来的是Android Studio插件的整理,全是我已经安装使用的,写这篇博文的目的也是因为我怕我自己给忘记怎么用(尴尬) ...
- .NET MVC5简介(四)Filter和AuthorizeAttribute权限验证
在webform中,验证的流程大致如下图: 在AOP中: 在Filter中: AuthorizeAttribute权限验证 登录后有权限控制,有的页面是需要用户登录才能访问的,需要在访问页面增加一个验 ...
- IIS 上部署 ASP.NET Core 应用程序
1.下载 .Net Core Runtime 和 Hosting Bundle 下载地址:https://dotnet.microsoft.com/download/dotnet-core 分别下载 ...
- toUpperCase(),toLowerCase()将字符串中的英文转换为全大写或全小写
package seday01;/** * String toUpperCase() * String toLowerCase() * 将字符串中的英文转换为全大写或全小写 * @author xin ...
- Java生鲜电商平台-B2B生鲜的互联网思维
Java生鲜电商平台-B2B生鲜的互联网思维 在互联网高速发展的今天,为我们的生活带来了众多便利.然而互联网从早期的萌芽状态到现在妇孺皆知,它的崛起速度远远超乎世人的想象.人们开始关注互联网并且研究它 ...
- 机器学习实战:基于Scikit-Learn和TensorFlow 读书笔记 第6章 决策树
数据挖掘作业,要实现决策树,现记录学习过程 win10系统,Python 3.7.0 构建一个决策树,在鸢尾花数据集上训练一个DecisionTreeClassifier: from sklearn. ...