[LOJ6281]数列分块入门 5

题目大意:
  给你一个长度为$n(n\leq50000)$的序列$A(0\leq A_i<2^{31})$,支持进行以下两种操作:
    1.将区间$[l,r]$中所有数开方;
    2.询问区间$[l,r]$的和。
思路:
  分块。
  因为当一个区间内的所有$A_i$都$\leq1$时,操作1对答案没有影响,因此我们可以记录每个区间是否还有操作的必要。如果还有大于$1$的数,就暴力进行操作,否则跳过。易证每个区间最多开方4次。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<algorithm>
 5 typedef long long int64;
 6 inline int getint() {
 7     register char ch;
 8     register bool neg=false;
 9     while(!isdigit(ch=getchar())) if(ch=='-') neg=true;
10     register int x=ch^'0';
11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
12     return neg?-x:x;
13 }
14 const int N=50001;
15 int val[N],bel[N],begin[N],end[N],max[N];
16 int64 sum[N];
17 inline void modify(const int &l,const int &r,const int &c) {
18     if(bel[l]==bel[r]) {
19         for(register int i=l;i<=r;i++) val[i]=sqrt(val[i]);
20         sum[bel[l]]=max[bel[l]]=0;
21         for(register int i=begin[bel[l]];i<=end[bel[l]];i++) {
22             sum[bel[l]]+=val[i];
23             max[bel[l]]=std::max(max[bel[l]],val[i]);
24         }
25         return;
26     }
27     for(register int i=l;bel[i]==bel[l];i++) val[i]=sqrt(val[i]);
28     for(register int i=r;bel[i]==bel[r];i--) val[i]=sqrt(val[i]);
29     for(register int i=bel[l]+1;i<bel[r];i++) {
30         if(max[i]==1) continue;
31         for(register int j=begin[i];j<=end[i];j++) val[j]=sqrt(val[j]);
32     }
33     for(register int i=bel[l];i<=bel[r];i++) {
34         if(max[i]==1) continue;
35         sum[i]=max[i]=0;
36         for(register int j=begin[i];j<=end[i];j++) {
37             sum[i]+=val[j];
38             max[i]=std::max(max[i],val[j]);
39         }
40     }
41 }
42 inline int64 query(const int &l,const int &r) {
43     int64 ret=0;
44     if(bel[l]==bel[r]) {
45         for(register int i=l;i<=r;i++) ret+=val[i];
46         return ret;
47     }
48     for(register int i=l;bel[i]==bel[l];i++) ret+=val[i];
49     for(register int i=r;bel[i]==bel[r];i--) ret+=val[i];
50     for(register int i=bel[l]+1;i<bel[r];i++) ret+=sum[i];
51     return ret;
52 }
53 int main() {
54     const int n=getint(),block=sqrt(n);
55     for(register int i=1;i<=n;i++) {
56         val[i]=getint();
57         bel[i]=i/block;
58         if(!begin[bel[i]]) begin[bel[i]]=i;
59         end[bel[i]]=i;
60         sum[bel[i]]+=val[i];
61         max[bel[i]]=std::max(max[bel[i]],val[i]);
62     }
63     for(register int i=0;i<n;i++) {
64         const int opt=getint(),l=getint(),r=getint(),c=getint();
65         if(opt) {
66             printf("%lld\n",query(l,r));
67         } else {
68             modify(l,r,c);
69         }
70     }
71     return 0;
72 }

 

posted @ 2018-02-15 14:39  skylee03  阅读(123)  评论(0编辑  收藏  举报