数列分块入门 5(及区间开方,区间求和)
题目链接:https://loj.ac/problem/6281
题目大意:中文题目
具体思路:具体的优化就是判断当期你的区间如果为1或者0的话,再开根就没有变化了,这样就不需要开根了,判断每一个块是否需要开根。
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 # define ll long long
4 const int maxn = 2e6+100;
5 const int inf = 0x3f3f3f3f;
6 ll l[maxn],r[maxn],belong[maxn];
7 ll add[maxn],a[maxn],sum[maxn];
8 bool flag[maxn];
9 int n;
10 void buildblock()
11 {
12 ll tmp=(ll)sqrt(n);
13 ll tot=n/tmp;
14 if(n%tmp)
15 tot++;
16 for(ll i=1; i<=n; i++)
17 {
18 belong[i]=(i-1)/tmp+1ll;
19 }
20 for(ll i=1; i<=tot; i++)
21 {
22 l[i]=(i-1)*tmp+1ll;
23 r[i]=i*tmp;
24 }
25 r[tot]=n;
26 for(int i=1; i<=tot; i++)
27 {
28 for(int j=l[i]; j<=r[i]; j++)
29 {
30 sum[i]+=a[j];
31 }
32 }
33 }
34 void update(ll st,ll ed)
35 {
36 if(belong[st]==belong[ed])
37 {
38 if(!flag[belong[st]])
39 return ;
40 for(int i=st; i<=ed; i++)
41 {
42 a[i]=(int)sqrt(a[i]);
43 }
44 flag[belong[st]]=0;
45 sum[belong[st]]=0;
46 for(int i=l[belong[st]]; i<=r[belong[st]]; i++)
47 {
48 sum[belong[st]]+=a[i];
49 if(a[i]>1)
50 flag[belong[st]]=1;
51 }
52 return ;
53 }
54 for(int i=st; i<=r[belong[st]]; i++)
55 {
56 a[i]=(int)sqrt(a[i]);
57 }
58 flag[belong[st]]=0;
59 sum[belong[st]]=0;
60 for(int i=l[belong[st]]; i<=r[belong[st]]; i++)
61 {
62 sum[belong[st]]+=a[i];
63 if(a[i]>1)
64 flag[belong[st]]=1;
65 }
66 for(int i=l[belong[ed]]; i<=ed; i++)
67 {
68 a[i]=(int)sqrt(a[i]);
69 }
70 flag[belong[ed]]=0;
71 sum[belong[ed]]=0;
72 for(int i=l[belong[ed]]; i<=r[belong[ed]]; i++)
73 {
74 sum[belong[ed]]+=a[i];
75 if(a[i]>1)
76 flag[belong[ed]]=1;
77 }
78 for(int i=belong[st]+1; i<belong[ed]; i++)
79 {
80 if(!flag[i])
81 continue;
82 flag[i]=0;
83 sum[i]=0;
84 for(int j=l[i]; j<=r[i]; j++)
85 {
86 a[j]=(int)sqrt(a[j]);
87 sum[i]+=a[j];
88 if(a[j]>1)
89 flag[i]=1;
90 }
91 }
92 }
93 ll ask(ll st,ll ed)
94 {
95 ll ans=0;
96 if(belong[st]==belong[ed])
97 {
98 for(int i=st; i<=ed; i++)
99 {
100 ans+=a[i];
101 }
102 return ans;
103 }
104 for(int i=st; i<=r[belong[st]]; i++)
105 {
106 ans+=a[i];
107 }
108 for(int i=l[belong[ed]]; i<=ed; i++)
109 {
110 ans+=a[i];
111 }
112 for(int i=belong[st]+1; i<belong[ed]; i++)
113 {
114 ans+=sum[i];
115 }
116 return ans;
117 }
118 int main()
119 {
120 memset(flag,1,sizeof(flag));
121 scanf("%d",&n);
122 for(int i=1; i<=n; i++)
123 {
124 scanf("%lld",&a[i]);
125 }
126 buildblock();
127 ll op,st,ed;
128 ll val;
129 while(n--)
130 {
131 scanf("%lld %lld %lld %lld",&op,&st,&ed,&val);
132 if(op==0)
133 {
134 update(st,ed);
135 }
136 else
137 {
138 printf("%lld\n",ask(st,ed));
139 }
140 }
141 return 0;
142 }