题面:https://www.codechef.com/problems/FNCS

题解:

我们考虑对 n 个函数进行分块,设块的大小为S。

每个块内我们维护当前其所有函数值的和,以及数组中每个元素对这个块函数值的和的贡献系数。

那么每次修改操作我们就可以对每个块函数值的和 O(1)进行修改。

对于询问,落在完整块内的部分我们维护了它的和,直接 O(1)调用即可。

剩余的部分我们对每个函数依次求值。

那么现在问题就变为单点修改、询问区间和。

如果我们使用树状数组,那么单次询问与单次修改复杂度操作均为 O(logn),

而询问操作数目远多于修改操作导致时间效率不平衡。

所以我们对原数组求一遍前缀和,然后问题变为区间修改、单点查询,

这个我们用分块便可以做到 O(S+n/S)修改和 O(1)询问了。

PS:此题卡long long,要用unsigned long long。。。

code:

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char ch;
bool ok;
void read(int &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
typedef unsigned long long int64;
const int maxs=;
const int maxn=;
int n,q,siz,lim,op,l,r,x,y,bel[maxn];
struct Data{
int l,r;
}block[maxs],seg[maxn];
int a[maxn];
int f[maxs][maxn];
int64 res[maxs],sum[maxs][maxs],tag[maxs];
struct Seg{
int add[maxn<<];
void init(){memset(add,,sizeof(add));}
void pushdown(int k){if (add[k]) add[k<<]+=add[k],add[(k<<)+]+=add[k],add[k]=;}
void modify(int k,int l,int r,int x,int y){
if (l==x&&r==y){add[k]++;return;}
int m=(l+r)>>;
if (y<=m) modify(k<<,l,m,x,y);
else if (x<=m) modify(k<<,l,m,x,m),modify((k<<)+,m+,r,m+,y);
else modify((k<<)+,m+,r,x,y);
}
void get(int k,int l,int r,int id){
if (l==r){f[id][l]=add[k],res[id]+=1ULL*add[k]*a[l];return;}
int m=(l+r)>>;
pushdown(k);
get(k<<,l,m,id),get((k<<)+,m+,r,id);
}
}T;
void add(int x,int v){
int id=bel[x],st=id;
if (x>block[id].l){
for (int i=x;i<=block[id].r;i++) sum[id][i-block[id].l]+=v;
st++;
}
for (int i=st;i<=lim;i++) tag[i]+=v;
}
int64 query(int x){
if (!x) return ;
int id=bel[x];
return sum[id][x-block[id].l]+tag[id];
}
void modify(int x,int v){
add(x,-a[x]);
for (int i=;i<=lim;i++) res[i]-=1ULL*f[i][x]*a[x];
a[x]=v;
add(x,a[x]);
for (int i=;i<=lim;i++) res[i]+=1ULL*f[i][x]*a[x];
}
void query(int l,int r){
int64 ans=;
int st=bel[l],ed=bel[r];
if (st!=ed){
if (l>block[st].l){
for (int i=l;i<=block[st].r;i++) ans+=query(seg[i].r)-query(seg[i].l-);
st++;
}
if (r<block[ed].r){
for (int i=block[ed].l;i<=r;i++) ans+=query(seg[i].r)-query(seg[i].l-);
ed--;
}
for (int i=st;i<=ed;i++) ans+=res[i];
}
else for (int i=l;i<=r;i++) ans+=query(seg[i].r)-query(seg[i].l-);
printf("%llu\n",ans);
}
int main(){
read(n),siz=sqrt(n);
for (int i=;i<=n;i++){
bel[i]=i/siz+;
if (!block[bel[i]].l) block[bel[i]].l=i;
block[bel[i]].r=i;
}
lim=bel[n];
for (int i=;i<=n;i++) read(a[i]),add(i,a[i]);
for (int i=;i<=n;i++){
if (block[bel[i]].l==i) T.init();
read(l),read(r),seg[i]=(Data){l,r};
T.modify(,,n,l,r);
if (block[bel[i]].r==i) T.get(,,n,bel[i]);
}
for (read(q);q;q--){
read(op),read(x),read(y);
if (op==) modify(x,y);
else query(x,y);
}
return ;
}

CodeChef FNCS的更多相关文章

  1. CodeChef FNCS (分块+树状数组)

    题目:https://www.codechef.com/problems/FNCS 题解: 我们知道要求区间和的时候,我们用前缀和去优化.这里也是一样,我们要求第 l 个函数到第 r 个函数 [l, ...

  2. Chef and Problems(from Code-Chef FNCS) ( 回 滚 )

    题目: 题意:给定序列,求[l,r]区间内数字相同的数的最远距离. 链接:https://www.codechef.com/problems/QCHEF #include<bits/stdc++ ...

  3. CodeChef - FNCS Chef and Churu(分块)

    https://vjudge.net/problem/CodeChef-FNCS 题意: 思路: 用分块的方法,对每个函数进行分块,计算出该分块里每个数的个数,这样的话也就能很方便的计算出这个分块里所 ...

  4. [codechef FNCS]分块处理+树状数组

    题目链接:https://vjudge.net/problem/CodeChef-FNCS 在一个地方卡了一晚上,就是我本来以为用根号n分组,就会分成根号n个.事实上并不是....因为用的是根号n下取 ...

  5. Codechef FNCS Chef and Churu

    Disciption Chef has recently learnt Function and Addition. He is too exited to teach this to his fri ...

  6. ZJOI2019一轮停课刷题记录

    Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...

  7. 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu

    https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...

  8. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1288  Solved: 490 ...

  9. 【BZOJ4260】 Codechef REBXOR 可持久化Trie

    看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...

随机推荐

  1. 洛谷 P1004 方格取数

    题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 ...

  2. hdu2817 A sequence of numbers

    这题就是判断是等差数列还是等比数列,然后计算结果mod200907 因为数字比较大10的九次方 所以等比用到了快速幂求模 不懂可以看看算法导论,在大数那里有讲 #include <iostrea ...

  3. 一个可视化的retrospective网站

    IdeaBoardz - Brainstorm, Retrospect, Collaborate是一个可视化的retrospective,brainstorm的网站,比较简单易用,可以导出pdf和ex ...

  4. leetcode题解||Reverse Integer 问题

    problem: Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321 ...

  5. [Android 中级]Voip之CSipSimple类库的编绎

    CSipSimple是什么?是一款基于pjsip的Android客户端,相信想要研究VOIP通讯的朋友一定不会陌生,这里我就把如何编译CSipSimple写下来. 首先从CSipSimple官方网站上 ...

  6. Java NIO——Selector机制源码分析---转

    一直不明白pipe是如何唤醒selector的,所以又去看了jdk的源码(openjdk下载),整理了如下: 以Java nio自带demo : OperationServer.java   Oper ...

  7. (转载)JavaScript中面向对象那点事

    鉴于自己在JavaScript这方面比较薄弱,所以就找了一本书恶补了一下(被称为犀利书的JavaScript权威指南).书的内容虽然多了点,但这也充分说明了js中的东西还是挺多的.虽然我们的定位不是前 ...

  8. Python之路【第十篇】:HTML -暂无等待更新

    Python之路[第十篇]:HTML -暂无等待更新

  9. 安卓数据存储(2):SharedPreferences

    SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对)在读取数据时可以通过这个键把相应的值取出 ...

  10. Linux试玩指令开机关机

    Linux内核最初只是由芬兰人李纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的. Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和U ...