洛谷 P4396 [AHOI2013]作业
题目描述
分析
因为询问是关于区间的,并且没有强制在线,所以能用莫队解决
但是还要支持查询区间内大于等于 \(a\),小于等于 \(b\) 的数的个数和数值的个数
所以还要套一个数据结构
比较好想的做法是对权值开一个数状数组
\(logn\) 修改,\(logn\) 查询
复杂度有点高
考虑莫队的本质是进行了 \(n\sqrt{m}\) 次修改和 \(m\) 次查询
我们的修改必须是 \(O(1)\) 的,但是查询的次数比较少,可以 \(O(\sqrt{n})\) 解决
所以可以用值域分块代替树状数组,可以做到 \(O(n\sqrt{m})\) 的复杂度
代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=1e6+5;
int n,m,a[maxn],blo,ans1[maxn],ans2[maxn],nans1,nans2,mmax,shuyu[maxn],cntcol[maxn],cntnum[maxn],cnt[maxn],lmax[maxn],rmax[maxn];
struct jie{
int l,r,jla,jlb,id;
jie(){}
jie(rg int aa,rg int bb,rg int cc,rg int dd,rg int ee){
l=aa,r=bb,jla=cc,jlb=dd,id=ee;
}
}b[maxn];
bool cmp(rg jie aa,rg jie bb){
if(shuyu[aa.l]==shuyu[bb.l]){
return shuyu[aa.l]&1?aa.r<bb.r:aa.r>bb.r;
} else {
return aa.l<bb.l;
}
}
void xg(rg int val,rg int op){
if(cnt[val]==0) cntcol[shuyu[val]]++;
cnt[val]+=op;
cntnum[shuyu[val]]+=op;
if(cnt[val]==0) cntcol[shuyu[val]]--;
}
void cx(rg int nl,rg int nr){
nans1=0,nans2=0;
for(rg int i=nl;i<=std::min(nr,rmax[shuyu[nl]]);i++){
nans1+=cnt[i];
nans2+=(cnt[i]!=0);
}
if(shuyu[nl]==shuyu[nr]) return;
for(rg int i=nr;i>=lmax[shuyu[nr]];i--){
nans1+=cnt[i];
nans2+=(cnt[i]!=0);
}
for(rg int i=shuyu[nl]+1;i<=shuyu[nr]-1;i++){
nans1+=cntnum[i];
nans2+=cntcol[i];
}
}
int main(){
memset(lmax,0x3f,sizeof(lmax));
n=read(),m=read();
for(rg int i=1;i<=n;i++) a[i]=read();
mmax=n;
rg int aa,bb,cc,dd;
for(rg int i=1;i<=m;i++){
aa=read(),bb=read(),cc=read(),dd=read();
mmax=std::max(mmax,bb);
b[i]=jie(aa,bb,cc,dd,i);
}
blo=sqrt(mmax);
for(rg int i=1;i<=mmax;i++){
shuyu[i]=(i-1)/blo+1;
lmax[shuyu[i]]=std::min(lmax[shuyu[i]],i);
rmax[shuyu[i]]=std::max(rmax[shuyu[i]],i);
}
std::sort(b+1,b+1+m,cmp);
rg int nl=1,nr=0;
for(rg int i=1;i<=m;i++){
while(nr<b[i].r) xg(a[++nr],1);
while(nl>b[i].l) xg(a[--nl],1);
while(nr>b[i].r) xg(a[nr--],-1);
while(nl<b[i].l) xg(a[nl++],-1);
cx(b[i].jla,b[i].jlb);
ans1[b[i].id]=nans1;
ans2[b[i].id]=nans2;
}
for(rg int i=1;i<=m;i++) printf("%d %d\n",ans1[i],ans2[i]);
return 0;
}
洛谷 P4396 [AHOI2013]作业的更多相关文章
- bzoj 3236: 洛谷 P4396: [AHOI2013]作业 (莫队, 分块)
题目传送门:洛谷P4396. 题意简述: 给定一个长度为\(n\)的数列.有\(m\)次询问,每次询问区间\([l,r]\)中数值在\([a,b]\)之间的数的个数,和数值在\([a,b]\)之间的不 ...
- 洛谷P4396 [AHOI2013]作业(树套树)
题意 题目链接 Sol 为什么一堆分块呀..三维数点不应该是套路离线/可持久化+树套树么.. 亲测树状数组套权值线段树可过 复杂度\(O(nlog^2n)\),空间\(O(nlogn)\)(离线) # ...
- 洛谷 P4396 (离散化+莫队+树状数组)
### 洛谷P4396 题目链接 ### 题目大意: 有 n 个整数组成的数组,m 次询问,每次询问中有四个参数 l ,r,a,b .问你在[l,r] 的区间内的所有数中,值属于[a,b] 的数的个 ...
- 线段树分治初步学习&洛谷P5227[AHOI2013]连通图
线段树分治 其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询balabala)全部拍到一棵线段树上,然后对着整棵树dfs一下求解答案,顺便把操作做一下,回溯的时候撤销一下即可.虽 ...
- 洛谷P4396 作业 [AHOI2013] 莫队
正解:莫队 解题报告: 传送门! 天呐太久没做莫队了连板子都认不出来了,,,所以复健下做下莫队的题目QAQ 就很板子鸭,和莫队板子比好像只有一个离散化,,,?就不讲了QAQ 等下直接放代码QAQ ov ...
- P4396 [AHOI2013]作业 分块+莫队
这个题正解是莫队+树状数组,但是我个人非常不喜欢树状数组这种东西,所以决定用分块来水这个题.直接在莫队维护信息的时候,维护单点同时维护块内信息就行了. 莫队就是这几行核心代码: void add(in ...
- 【题解】Luogu P4396 [AHOI2013]作业
原题传送门 最快的解法好像是cdq,但窝只会莫队+线段树/树状数组的做法 题目要我们求1.在区间[l,r]中值域在[a,b]中有多少个数2.在区间[l,r]中值域在[a,b]中有多少个不同数 一眼就看 ...
- luogu P4396 [AHOI2013]作业
目录 题目 思路 错误&&傻叉 代码 题目 luogu 思路 每次都是插入比之前所有数字大的数,所以之前的答案就不会改变 用fhq-treap求出原序列,然后用树状数组依次算出每个值得 ...
- P4396 [AHOI2013]作业
题目链接 luogu4396 思路 唯有水题暖人心 咕了4天,今天跟着std对拍才做出来不得不说题解真的水的一批 先离散化一下 第一问差分询问,权值树状数组套一套就好了 \(nlog_{n}\) 第二 ...
随机推荐
- flask实现分类搜索的小测试
最新学长要求实现一个搜索的功能呢,也费了一点功夫.这个案例也没有学长写的好,比学长的实现差了不少,待我仔细研究习再发出相应代码 项目要求,搜索语法如下: titile: xxx #搜索titile的所 ...
- 图论——迪杰斯特拉算法(Dijkstra)实现,leetcode
迪杰斯特拉算法(Dijkstra):求一点到另外一点的最短距离 两种实现方法: 邻接矩阵,时间复杂度O(n^2) 邻接表+优先队列,时间复杂度O(mlogn)(适用于稀疏图) (n:图的节点数,m:图 ...
- 科大讯飞语音合成系统 V5.0绿色便携版
中文名: 中科大讯飞Interphonic 5.0语音合成系统英文名: Interphonic 5.0版本: 5.0发行时间: 2006年制作发行: 中科大讯飞语言: 简体中文系统简介InterPho ...
- 中间件面试专题:RabbitMQ高频面试问题
- 第六篇 Scrum 冲刺博客
一.站立式会议 1. 会议照片 2. 工作汇报 团队成员名称 昨日完成的工作 今天计划完成的工作 工作中遇到的困难 陈锐基 - 完成关注/取关功能以及动态绑定- 完成点赞/取消点赞功能以及动态绑定 - ...
- Codeforces Edu Round 63 A-E
A. Reverse a Substring 容易看出,只要符合递增顺序就符合\(NO\),否则则可以找到一组,每次记录最大值比较即可. #include <cstdio> #includ ...
- 【APIO2018】选圆圈(平面分块 | CDQ分治 | KDT)
Description 给定平面上的 \(n\) 个圆,用三个参数 \((x, y, R)\) 表示圆心坐标和半径. 每次选取最大的一个尚未被删除的圆删除,并同时删除所有与其相切或相交的圆. 最后输出 ...
- STL——容器(Map & multimap)的大小
1. Map & multimap 的大小 map.size(); //返回容器中元素的数目 map.empty();//判断容器是否为空, 容器中有内容将会返回 false 代码示例 ...
- STL—— 容器(vector)数据插入insert()方法 的返回值
vector 容器下的 insert() 方法拥有返回值,由于insert() 方法拥有4种重载函数,他的返回值不尽相同. 第一种,插入单个元素后的返回值: 1 #include <iostre ...
- sql server如何把退款总金额拆分到尽量少的多个订单中
一.问题 原来有三个充值订单,现在要退款450元,如何分配才能让本次退款涉及的充值订单数量最少?具体数据参考下图: 二.解决方案 Step 1:对可退金额进行降序排列,以便优先使用可退金额比较大的订单 ...