描述

有n个小朋友需要接水,其中第i个小朋友接水需要ai分钟。

由于水龙头有限,小Hi需要知道如果为第l个到第r个小朋友分配一个水龙头,如何安排他们的接水顺序才能使得他们等待加接水的时间总和最小。

小Hi总共会有m次询问,你能帮助他解决这个问题吗?

假设3个小朋友接水的时间分别是2,3,4。如果他们依次接水,第一位小朋友等待加接水的时间是2,第二位小朋友是5,第三位小朋友是9。时间总和是16。

输入

第一行一个数T(T<=10),表示数据组数

对于每一组数据:

第一行两个数n,m(1<=n,m<=20,000)

第二行n个数a1...an,表示每个小朋友接水所需时间(ai<=20,000)

接下来m行,每行两个数l和r

输出

对于每次询问,输出一行一个整数,表示答案。

样例输入

1
4 2
1 2 3 4
1 2
2 4

样例输出

4
16

思路:贪心可知,时间小的在前。但是排序是不可能的,需要更高效的方法,注意到ai<=2e5,适合用树状数组记录a[i]的个数前缀和,以及a[i]的前缀和。

可以离线,所以用莫队+树状数组,莫队的话,第一次写这中数学类型的转移,开始还有点抵触,但是拿出笔一划,公式也不难。

对于暴力的公式,即L<=i<=R的所有i的前缀和:

for(i=L;i<=R;i++)
for(j=L;j<=i;j++)
sum+=a[j];

那么现在加一个第i=x进去,则对新的 i=x,需要多累加前缀:

for(j=L;j<=x;j++)
sum+=a[j];

对于后面的i>=x,都需要累加一个j=x,即a[x]*后面的个数。

for(i=x;i<=R;i++)
for(j=L;j<=i;j++)
sum+=a[j];

然后把上面的转化为树状数组的前缀和即可。  两个树状数组,分别记录个数和累加和。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=;
ll a[maxn+],num[maxn+],cnt,B,l,r,tmp;
ll sum[maxn+];
struct in{ ll L;ll R;ll id; ll ans;}s[maxn+];
bool cmp(in x,in y){ if(x.L/B==y.L/B) return x.R/B<y.R/B; return x.L/B<y.L/B; }
bool cmp2(in x,in y){ return x.id<y.id;}
void update(){ cnt=; memset(num,,sizeof(num));memset(sum,,sizeof(sum)); }
void addnum(ll x,ll y) { while(x<=maxn){ num[x]+=y; x+=(-x)&x; } }
void addsum(ll x,ll y) { while(x<=maxn){ sum[x]+=y; x+=(-x)&x; } }
int querynum(int x){ ll res=; while(x>){ res+=num[x]; x-=(-x)&x;} return res; }
int querysum(int x){ ll res=; while(x>){ res+=sum[x]; x-=(-x)&x;} return res;}
int main()
{ ll T,n,m,i;ll tsum;
scanf("%d",&T);
while(T--){
update();
scanf("%lld%lld",&n,&m);
for(i=;i<=n;i++) scanf("%lld",&a[i]);
for(i=;i<=m;i++) s[i].id=i,scanf("%lld%lld",&s[i].L,&s[i].R);
B=sqrt(n);
sort(s+,s+m+,cmp);
l=r=; tmp=a[]; addnum(a[],); addsum(a[],a[]);
for(i=;i<=m;i++){
while(l<s[i].L){
tsum=querysum(a[l]);
tmp-=tsum;
tmp-=(querynum(maxn)-querynum(a[l]))*a[l];
addnum(a[l],-);
addsum(a[l],-a[l]);
l++;
}
while(l>s[i].L){
l--;
addnum(a[l],);
addsum(a[l],a[l]);
tsum=querysum(a[l]);
tmp+=tsum;
tmp+=(querynum(maxn)-querynum(a[l]))*a[l];
}
while(r<s[i].R){
r++;
addnum(a[r],);
addsum(a[r],a[r]);
tsum=querysum(a[r]);
tmp+=tsum;
tmp+=(querynum(maxn)-querynum(a[r]))*a[r];
}
while(r>s[i].R){
tsum=querysum(a[r]);
tmp-=tsum;
tmp-=(querynum(maxn)-querynum(a[r]))*a[r];
addnum(a[r],-);
addsum(a[r],-a[r]);
r--;
}
s[i].ans=tmp;
}
sort(s+,s+m+,cmp2);
for(i=;i<=m;i++) printf("%lld\n",s[i].ans);
}
return ;
}

HihoCoder 1488 : 排队接水(莫队+树状数组)的更多相关文章

  1. 【BZOJ3460】Jc的宿舍(树上莫队+树状数组)

    点此看题面 大致题意: 一棵树,每个节点有一个人,他打水需要\(T_i\)的时间,每次询问两点之间所有人去打水的最小等待时间. 伪·强制在线 这题看似强制在线,但实际上,\(pre\ mod\ 2\) ...

  2. bzoj3236 作业 莫队+树状数组

    莫队+树状数组 #include<cstdio> #include<cstring> #include<iostream> #include<algorith ...

  3. BZOJ_3289_Mato的文件管理_莫队+树状数组

    BZOJ_3289_Mato的文件管理_莫队+树状数组 Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号 .为了防止他人 ...

  4. BZOJ3236[Ahoi2013]作业——莫队+树状数组/莫队+分块

    题目描述 输入 输出 样例输入 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 样例输出 2 2 1 1 3 2 2 1 提示 N=100000,M=1000000 ...

  5. COGS.1822.[AHOI2013]作业(莫队 树状数组/分块)

    题目链接: COGS.BZOJ3236 Upd: 树状数组实现的是单点加 区间求和,采用值域分块可以\(O(1)\)修改\(O(sqrt(n))\)查询.同BZOJ3809. 莫队为\(O(n^{1. ...

  6. bzoj 3289: Mato的文件管理 莫队+树状数组

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Mato同学 ...

  7. 51nod 1290 Counting Diff Pairs | 莫队 树状数组

    51nod 1290 Counting Diff Pairs | 莫队 树状数组 题面 一个长度为N的正整数数组A,给出一个数K以及Q个查询,每个查询包含2个数l和r,对于每个查询输出从A[i]到A[ ...

  8. BZOJ 3236 莫队+树状数组

    思路: 莫队+树状数组 (据说此题卡常数) yzy写了一天(偷笑) 复杂度有点儿爆炸 O(msqrt(n)logn) //By SiriusRen #include <cmath> #in ...

  9. BZOJ 3236: [Ahoi2013]作业(莫队+树状数组)

    传送门 解题思路 莫队+树状数组.把求\([a,b]\)搞成前缀和形式,剩下的比较裸吧,用\(cnt\)记一下数字出现次数.时间复杂度\(O(msqrt(n)log(n)\),莫名其妙过了. 代码 # ...

随机推荐

  1. Android自己定义组件系列【6】——进阶实践(3)

    上一篇<Android自己定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计 ...

  2. HttpClient获取Cookie的两种方式

    转载:http://blog.csdn.net/zhangbinu/article/details/72777620 一.旧版本的HttpClient获取Cookies p.s. 该方式官方已不推荐使 ...

  3. PS 基础知识 CMYK全称是什么

    已解决 请问谁知道CMYK四色的英文全称? 悬赏分:20 - 解决时间:2006-9-6 16:23 C代表什么颜色?英文全称是什么? M代表什么颜色?英文全称是什么? Y代表什么颜色?英文全称是什么 ...

  4. Android Developer:Allocation Tracker演示

    这个演示展示了Allocation Tracker工具在Android Studio中的基本使用方法和流程. Allocation Tracker记录了一个app的内存分配,列出全部分配对象,用于分析 ...

  5. 介绍一个开源的SIP(VOIP)协议库PJSIP

    本文系转载,出处不可考. 假设你对SIP/VoIP技术感兴趣,哪希望你不要错过:),假设你对写出堪称优美的Code感兴趣 ,那么你也不可错过:) 这期间我想分析一下一个实际的协议栈的设计到实现的相关技 ...

  6. 【转载】ASP.NET应用程序与页面生命周期

    在本文中,我们将了解不同的事件,ASP.NET 应用程序的生命周期以浏览器向 Web 服务器(对于 ASP.NET 应用程序,通常为 IIS)发送请求为起点,直至将请求结果返回至浏览器结束.在这个过程 ...

  7. 函数式编程( Functional)与命令式编程( Imperative)对比

    1.函数式编程带来的好处 函数式编程近些年异军突起,又重新回到了人们的视线,并得到蓬勃发展.总结起来,无外乎如下好处: 1.减少了可变量(Immutable Variable)的声明,程序更为安全.  ...

  8. 虚幻4Matinee功能 基本概念及简单演示样例(Sequence编辑器)

    虚幻4提供的Matinee功能十分强大,能够用来制作动画.录制视频. 它的核心想法是在Matinee编辑器内提供一套自己的时间坐标系,在这个相对时间内通过调节actor的属性来改变actor的状态,进 ...

  9. SD 卡PIN定义

    转载:http://blog.sina.com.cn/s/blog_56e19aa70101avnw.html SD卡和TF卡接口引脚定义  

  10. React项目结构

    任何一种语言.框架,在真正上手的时候,多多少少会想想怎么安排项目结构(正所谓磨刀不误砍柴工),React也不例外. google了下,拿下面3篇博客来说道说道. (1) how-to-better-o ...