CodeChef FNCS
题面: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的更多相关文章
- CodeChef FNCS (分块+树状数组)
题目:https://www.codechef.com/problems/FNCS 题解: 我们知道要求区间和的时候,我们用前缀和去优化.这里也是一样,我们要求第 l 个函数到第 r 个函数 [l, ...
- Chef and Problems(from Code-Chef FNCS) ( 回 滚 )
题目: 题意:给定序列,求[l,r]区间内数字相同的数的最远距离. 链接:https://www.codechef.com/problems/QCHEF #include<bits/stdc++ ...
- CodeChef - FNCS Chef and Churu(分块)
https://vjudge.net/problem/CodeChef-FNCS 题意: 思路: 用分块的方法,对每个函数进行分块,计算出该分块里每个数的个数,这样的话也就能很方便的计算出这个分块里所 ...
- [codechef FNCS]分块处理+树状数组
题目链接:https://vjudge.net/problem/CodeChef-FNCS 在一个地方卡了一晚上,就是我本来以为用根号n分组,就会分成根号n个.事实上并不是....因为用的是根号n下取 ...
- Codechef FNCS Chef and Churu
Disciption Chef has recently learnt Function and Addition. He is too exited to teach this to his fri ...
- ZJOI2019一轮停课刷题记录
Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...
- 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu
https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...
- 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1288 Solved: 490 ...
- 【BZOJ4260】 Codechef REBXOR 可持久化Trie
看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...
随机推荐
- win7不能在同一窗口打开文件夹,解决办法
1.由于IE浏览器的主页被劫持,总是忽然弹出搜狗的主页,有的时候,忽然弹出IE浏览器(主页是搜狗),然后又自行关闭,我X,我的电脑竟然不受我控制,这可得了,这里我又要骂宁美国度了,made,组装机装了 ...
- [置顶] Android布局管理器 - 详细解析布局实现
布局管理器都是以ViewGroup为基类派生出来的; 使用布局管理器可以适配不同手机屏幕的分辨率,尺寸大小; 布局管理器之间的继承关系 : 在上面的UML图中可以看出, 绝对布局 帧布局 网格布局 相 ...
- java 深clone和浅clone
1. clone类 public class Person implements Cloneable, Serializable{ /** * */ private static final long ...
- Git学习(一) 版本号管理工具
Git 是一个分布式版本号控制工具.它的作者 Linus Torvalds 是这样给我们介绍 Git -- The stupid content tracker(傻瓜式的内容跟踪器) 1. Git ...
- 内核与内核模块:depmod,lsmod,modinfo,insmod,rmmod,mdprobe
内核模块:/lib/modules/version/kernel或/lib/modules/$(uname -r)/kernel; [root@localhost kern ...
- Qt 学习之路:Canvas
在 QML 刚刚被引入到 Qt 4 的那段时间,人们往往在讨论 Qt Quick 是不是需要一个椭圆组件.由此,人们又联想到,是不是还需要其它的形状?这种没玩没了的联想导致了一个最直接的结果:除了圆角 ...
- Call Directory Extension 初探
推荐序 本文介绍了 iOS 10 中的 Call Directory Extension 特性,并且最终 Demo 出一个来电黑名单的 App. 作者:余龙泽,哈工大软件工程大四学生,之前在美图公司实 ...
- Java基础知识强化之集合框架笔记20:数据结构之 栈 和 队列
1. 栈 先进后出 解析图: 2. 队列 先进先出 解析图:
- HDU 4294 Multiple(搜索+数学)
题意: 给定一个n,让求一个M,它是n个倍数并且在k进制之下 M的不同的数字最少. 思路: 这里用到一个结论就是任意两个数可以组成任何数的倍数.知道这个之后就可以用搜索来做了.还有一个问题就是最多找n ...
- java返回参数中几种常见的方法
1.有参数有返回值 public class text_1 { 1)创建add方法 public int add(int i, int j) { int res = i + j; ...