• 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 }
  • 相关阅读:
    2018-10-25 模拟测试题解
    bzoj1218 [HNOI2003]激光炸弹题解
    poj1958 Strange Towers of Hanoi 题解
    NOIP2018游记
    6-序列公共用法:索引和切片
    5-编码格式
    4-格式化
    3-课后习题记录-就放这里了
    2-条件语句和循环语句
    1-基本数据类型的操作
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5275753.html
Copyright © 2020-2023  润新知