描述

有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. vu 是什么

    unsigned char 是无符号字符型 volatile      易变,易失的 volatile  unsigned char i; 意思是定义一个无符号字符型的变量 i. 这个变量存放在内存中 ...

  2. angular - 配置package.json -3

    package.json 包含了所有的开发包以及全局包以及其它项目信息,我们这个项目需要用到 bootstrap,所以我们添加信息. 添加包信息以后,我们用 npm install 安装,npm包管理 ...

  3. python(19)- 列表生成式和生成器表达式练习Ⅰ

    列表表达式 程序一: 常规写法: egg_list=[] for i in range(100): egg_list.append('egg%s' %i) print(egg_list) 列表表达式写 ...

  4. js replace 全局替换 以表单的方式提交参数 判断是否为ie浏览器 将jquery.qqFace.js表情转换成微信的字符码 手机端省市区联动 新字体引用本地运行可以获得,放到服务器上报404 C#提取html中的汉字 MVC几种找不到资源的解决方式 使用Windows服务定时去执行一个方法的三种方式

    js replace 全局替换   js 的replace 默认替换只替换第一个匹配的字符,如果字符串有超过两个以上的对应字符就无法进行替换,这时候就要进行一点操作,进行全部替换. <scrip ...

  5. javascript 连续赋值(转载)

    先看一个例子   ● var a = {n:1}; ● var b = a; ● a.x = a = {n:2}; ● console.log("a.x: " + a.x); // ...

  6. linux的su和sudo(转载)

    来源:http://www.jb51.net/LINUXjishu/12713.html 一. 使用 su 命令临时切换用户身份 1.su 的适用条件和威力 su命令就是切换用户的工具,怎么理解呢?比 ...

  7. iphone开发的技巧

    一,改动状态栏: 1.增加[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];但此方法仅仅是不显示状态条,状态 ...

  8. 未开启HugePages ORACLE session剧增时引起的一次悲剧

    故障简单描写叙述一下:LINUX系统未开启HugePages,主机内存将近300G.SWAP是32G.ORACLE 的 SGA_MAX_SIZE设置是主机内存的将近80%,SGA_TARGET设置是主 ...

  9. ajax跨域请求的问题

    使用getJson跨域请求,需要向服务器发送一个参数callback=? $.getJSON("http://appcenter.mobitide.com/admin/appSearch.p ...

  10. File syncing and sharing software with file encryption and group sharing, emphasis on reliability and high performance.

    http://seafile.com/ showdoc haiwen/seafile: File syncing and sharing software with file encryption a ...