【CODECHEF】Chef and Churus

Description

有一个长度为\(n\)的数组\(A\),有\(n\)个函数,第\(i\)个函数的值为\(\sum_{j=l_i}^{r_i}A_j\)

有两种操作:

①修改\(A_i\)

②询问第\(l\)~\(r\)个函数值的和。


Input

First Line is the size of the array i.e. N

Next Line contains N space separated numbers Ai denoting the array

Next N line follows denoting Li and Ri for each functions.

Next Line contains an integer Q , number of queries to follow.

Next Q line follows , each line containing a query of Type 1 or Type 2.

1 x y : denotes a type 1 query,where x and y are integers

2 m n : denotes a type 2 query where m and n are integers

Output

For each query of type 2 , output as asked above.


说明

\(1 ≤ N ≤ 10^5,1 ≤ A_i ≤ 10^9,1 ≤ L_i ≤ N,L_i ≤ R_i ≤ N,1 ≤ Q ≤ 10^5\)

\(1 ≤ x ≤ N,1 ≤ y ≤ 10^9,1 ≤ m ≤ N,m ≤ n ≤ N\)


一开始想了个做法,大概是把询问放到线段树的节点上,线段树维护区间和,外面用树状数组维护询问前缀和,然后每次修改的时候暴力改修改一条链的线段树节点上对树状数组的贡献。写完了感觉复杂度有点不对,好像是三个\(\log\)的,又好像可以卡,反正T掉了。

然后正解分块的思路真是神仙%%

对\(A\)进行分块,块内维护快内前缀和,块外维护块的前缀和。这样我们单点修改可以\(O(\sqrt n)\)做,但是询问区间和居然是\(O(1)\)的。

然后对询问进行分块,每个块\(i\)维护一个\(dev_{i,j}\)代表块\(i\)中所有函数覆盖了几个\(j\)这个位置,可以差分进行预处理,再维护一个\(sum_i\)表示这一整块的答案。然后我们发现修改的时候遍历一遍所有块就行了,复杂度是\(O(\sqrt n)\)的

询问的时候,整块直接用\(sum\),散块直接暴力查询区间就可以,复杂度\(O(\sqrt n)\)

于是总复杂度是\(O(n\sqrt n)\)

注意开ull


Code:

#include <cstdio>
#include <cmath>
#define ll unsigned long long
const int N=100010;
const int M=320;
ll F[M],f[N],a[N],sum[M];
int L[N],R[N],dev[M][N],Belong[N],ql[N],qr[N],T,num,n,m;
ll ask(int l,int r)//询问区间的和
{
int lp=Belong[l],rp=Belong[r];
if(lp==rp) return f[r]-(l==L[lp]?0:f[l-1]);
return f[R[lp]]-(l==L[lp]?0:f[l-1])+F[rp-1]-F[lp]+f[r];
}
void modify(int x,ll d)
{
int pos=Belong[x];//改数组块
for(int i=x;i<=R[pos];i++)
f[i]+=d-a[x];
for(int i=pos;i<=num;i++)
F[i]+=d-a[x];
for(int i=1;i<=num;i++)//改询问块
sum[i]+=(d-a[x])*dev[i][x];
a[x]=d;
}
ll query(int l,int r)
{
int lp=Belong[l],rp=Belong[r];
ll ret=0;
if(lp==rp)
{
for(int i=l;i<=r;i++)
ret+=ask(ql[i],qr[i]);
}
else
{
for(int i=l;i<=R[lp];i++)
ret+=ask(ql[i],qr[i]);
for(int i=L[rp];i<=r;i++)
ret+=ask(ql[i],qr[i]);
for(int i=lp+1;i<rp;i++)
ret+=sum[i];
}
return ret;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%llu",f+i),a[i]=f[i];
T=sqrt(n)+1;
for(num=1;num*T<=n;num++) L[num]=T*(num-1)+1,R[num]=T*num;--num;
if(R[num]<n) L[num+1]=R[num]+1,R[++num]=n;
for(int i=1;i<=num;i++)
{
Belong[L[i]]=i;
for(int j=L[i]+1;j<=R[i];j++)
f[j]+=f[j-1],Belong[j]=i;
F[i]+=f[R[i]]+F[i-1];
}
for(int i=1;i<=n;i++) scanf("%d%d",ql+i,qr+i);
for(int i=1;i<=num;i++)
{
for(int j=L[i];j<=R[i];j++)
++dev[i][ql[j]],--dev[i][qr[j]+1];
for(int j=1;j<=n;j++)
dev[i][j]+=dev[i][j-1],sum[i]+=1ll*dev[i][j]*a[j];
}
scanf("%d",&m);
for(int op,l,r,i=1;i<=m;i++)
{
scanf("%d%d%d",&op,&l,&r);
if(op==1) modify(l,r);
else printf("%llu\n",query(l,r));
}
return 0;
}

2018.12.13

CODECHEF Chef and Churus 解题报告的更多相关文章

  1. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  2. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  3. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

  4. 习题:codevs 2822 爱在心中 解题报告

    这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...

  5. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

  6. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  7. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

  8. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  9. LeetCode 解题报告索引

    最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中......                        ...

随机推荐

  1. 将 Python3 文件打包成 exe 文件

    我们用 Python 写好的代码,如何给别人在没有配置 Python 环境的情况下直接使用呢?尤其是面向 windows 众. 因为 Python 是一门解释性的语言,离开了 Python 解释器,P ...

  2. 前端--再遇jQuery

    一.属性 属性(如果你的选择器选出了多个对象,那么默认只会返回第一个属性) attr(属性名|属性值) --一个参数是获取属性的值,两个参数是设置属性值 --点击图片加载示例 removeAttr(属 ...

  3. 算法与AI的暗黑面:3星|《算法的陷阱:超级平台、算法垄断与场景欺骗》

    算法的陷阱:超级平台.算法垄断与场景欺骗 全书讲算法与AI的暗黑面:价格歧视.导致算法军备竞赛.导致商家降价冲动降低.平台作恶(向劣质商家收费导致品质下降.与开发商一起分析用户隐私)等. 作者从商业. ...

  4. JavaScript学习笔记(二)——函数和数组

    第二章 函数简介 1 第一个函数示例 <script language="JavaScript" type="text/JavaScript"> f ...

  5. jQuery 判断浏览器

    jQuery 浏览器判断,jQuery提供了一个 jQuery.browser 方法 来判断浏览器 可用值: safari   opera   msie   mozilla 例如:if($.brows ...

  6. ES6的新特性(11)——Class 的继承

    Class 的继承 简介 Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多. class Point { } class ColorPoint ...

  7. Hybrid APP基础篇(四)->JSBridge的原理

    说明 JSBridge实现原理 目录 前言 参考来源 前置技术要求 楔子 原理概述 简介 url scheme介绍 实现流程 实现思路 第一步:设计出一个Native与JS交互的全局桥对象 第二步:J ...

  8. 查看struts包源码

  9. Maya脚本——重命名物体的名称

    该脚本用于将图1中的命名变更为图2中的,把maya中使用相同名称的物体都重命名为不同的名称. 重命名的规则是:组名_原名称_序号 查阅了maya的官方手册:http://download.autode ...

  10. jQuery之属性

    1. 操作任意属性 attr() 操作非布尔值的 removeAttr() prop() 操作布尔值的2. 操作class属性 addClass() 添加class属性 removeClass() 移 ...