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:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 using namespace std;
  7 char ch;
  8 bool ok;
  9 void read(int &x){
 10     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
 11     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
 12     if (ok) x=-x;
 13 }
 14 typedef unsigned long long int64;
 15 const int maxs=320;
 16 const int maxn=100005;
 17 int n,q,siz,lim,op,l,r,x,y,bel[maxn];
 18 struct Data{
 19     int l,r;
 20 }block[maxs],seg[maxn];
 21 int a[maxn];
 22 int f[maxs][maxn];
 23 int64 res[maxs],sum[maxs][maxs],tag[maxs];
 24 struct Seg{
 25     int add[maxn<<2];
 26     void init(){memset(add,0,sizeof(add));}
 27     void pushdown(int k){if (add[k]) add[k<<1]+=add[k],add[(k<<1)+1]+=add[k],add[k]=0;}
 28     void modify(int k,int l,int r,int x,int y){
 29         if (l==x&&r==y){add[k]++;return;}
 30         int m=(l+r)>>1;
 31         if (y<=m) modify(k<<1,l,m,x,y);
 32         else if (x<=m) modify(k<<1,l,m,x,m),modify((k<<1)+1,m+1,r,m+1,y);
 33         else modify((k<<1)+1,m+1,r,x,y);
 34     }
 35     void get(int k,int l,int r,int id){
 36         if (l==r){f[id][l]=add[k],res[id]+=1ULL*add[k]*a[l];return;}
 37         int m=(l+r)>>1;
 38         pushdown(k);
 39         get(k<<1,l,m,id),get((k<<1)+1,m+1,r,id);
 40     }
 41 }T;
 42 void add(int x,int v){
 43     int id=bel[x],st=id;
 44     if (x>block[id].l){
 45         for (int i=x;i<=block[id].r;i++) sum[id][i-block[id].l]+=v;
 46         st++;
 47     }
 48     for (int i=st;i<=lim;i++) tag[i]+=v;
 49 }
 50 int64 query(int x){
 51     if (!x) return 0;
 52     int id=bel[x];
 53     return sum[id][x-block[id].l]+tag[id];
 54 }
 55 void modify(int x,int v){
 56     add(x,-a[x]);
 57     for (int i=1;i<=lim;i++) res[i]-=1ULL*f[i][x]*a[x];
 58     a[x]=v;
 59     add(x,a[x]);
 60     for (int i=1;i<=lim;i++) res[i]+=1ULL*f[i][x]*a[x];
 61 }
 62 void query(int l,int r){
 63     int64 ans=0;
 64     int st=bel[l],ed=bel[r];
 65     if (st!=ed){
 66         if (l>block[st].l){
 67             for (int i=l;i<=block[st].r;i++) ans+=query(seg[i].r)-query(seg[i].l-1);
 68             st++;
 69         }
 70         if (r<block[ed].r){
 71             for (int i=block[ed].l;i<=r;i++) ans+=query(seg[i].r)-query(seg[i].l-1);
 72             ed--;
 73         }
 74         for (int i=st;i<=ed;i++) ans+=res[i];
 75     }
 76     else for (int i=l;i<=r;i++) ans+=query(seg[i].r)-query(seg[i].l-1);
 77     printf("%llu
",ans);
 78 }
 79 int main(){
 80     read(n),siz=sqrt(n);
 81     for (int i=1;i<=n;i++){
 82         bel[i]=i/siz+1;
 83         if (!block[bel[i]].l) block[bel[i]].l=i;
 84         block[bel[i]].r=i;
 85     }
 86     lim=bel[n];
 87     for (int i=1;i<=n;i++) read(a[i]),add(i,a[i]);
 88     for (int i=1;i<=n;i++){
 89         if (block[bel[i]].l==i) T.init();
 90         read(l),read(r),seg[i]=(Data){l,r};
 91         T.modify(1,1,n,l,r);        
 92         if (block[bel[i]].r==i) T.get(1,1,n,bel[i]);
 93     }
 94     for (read(q);q;q--){
 95         read(op),read(x),read(y);
 96         if (op==1) modify(x,y);
 97         else query(x,y);
 98     }
 99     return 0;
100 }
原文地址:https://www.cnblogs.com/chenyushuo/p/5275753.html