BZOJ 3038上帝造题的七分钟2

题面:

3038: 上帝造题的七分钟2

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1450  Solved: 620
[Submit][Status][Discuss]

Description

XLk觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。
"第一分钟,X说,要有数列,于是便给定了一个正整数数列。
第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作。
第三分钟,k说,要能查询,于是便有了求一段数的和的操作。
第四分钟,彩虹喵说,要是noip难度,于是便有了数据范围。
第五分钟,诗人说,要有韵律,于是便有了时间限制和内存限制。
第六分钟,和雪说,要省点事,于是便有了保证运算过程中及最终结果均不超过64位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。"
——《上帝造题的七分钟·第二部》
所以这个神圣的任务就交给你了。

Input

第一行一个整数n,代表数列中数的个数。
第二行n个正整数,表示初始状态下数列中的数。
第三行一个整数m,表示有m次操作。
接下来m行每行三个整数k,l,r,k=0表示给[l,r]中的每个数开平方(下取整),k=1表示询问[l,r]中各个数的和。

Output

对于询问操作,每行输出一个回答。

Sample Input

10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8

Sample Output

19
7
6

HINT

1:对于100%的数据,1<=n<=100000,1<=l<=r<=n,数列中的数大于0,且不超过1e12。

2:数据不保证L<=R 若L>R,请自行交换L,R,谢谢!

可以发现,数列中的数至多经过6次开根就会变成1。

对每块打上标记,记录是否全变成1。

若是,那就不用再更新下去。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<math.h>
 4 using namespace std;
 5 #define maxn 100001
 6 #define LL long long
 7 LL a[maxn],s[maxn];
 8 int pos[maxn];
 9 bool flag[maxn];
10 int n,m,len;
11 void pushup(int x)
12 {
13     if(flag[x]==true)
14         return ;
15     flag[x]=true;
16     s[x]=0;
17     int l=(x-1)*len+1,r=min(x*len,n);
18     for(int i=l;i<=r;i++)
19     {
20         a[i]=sqrt(a[i]);
21         s[x]+=a[i];
22         if(s[x]>(r-l+1))
23             flag[x]=false;
24     }
25 }
26 void update(int l,int r)
27 {
28     if(pos[l]==pos[r])
29     {
30         for(int i=l;i<=r;i++)
31         {
32             s[pos[l]]-=a[i];
33             a[i]=sqrt(a[i]);
34             s[pos[l]]+=a[i];        
35         }
36     }
37     else
38     {
39         int L=pos[l]*len,R=(pos[r]-1)*len+1;
40         for(int i=l;i<=L;i++)
41         {
42             s[pos[l]]-=a[i];
43             a[i]=sqrt(a[i]);
44             s[pos[l]]+=a[i];
45         }
46         for(int i=R;i<=r;i++)
47         {
48             s[pos[r]]-=a[i];
49             a[i]=sqrt(a[i]);
50             s[pos[r]]+=a[i];
51         }
52         for(int i=pos[l]+1;i<=pos[r]-1;i++)
53             pushup(i);
54     }
55 }
56 LL query(int l,int r)
57 {
58     LL ans=0;
59     if(pos[l]==pos[r])
60     {
61         for(int i=l;i<=r;i++)
62             ans+=a[i];
63     }
64     else
65     {
66         int L=pos[l]*len,R=(pos[r]-1)*len+1;
67         for(int i=l;i<=L;i++)
68             ans+=a[i];
69         for(int j=R;j<=r;j++)
70             ans+=a[j];
71         for(int i=pos[l]+1;i<pos[r];i++)
72             ans+=s[i];
73     }
74     return ans;
75 }
76 int main()
77 {
78     int x,y,z;
79     scanf("%d",&n);
80     len=90;
81     for(int i=1;i<=n;i++)
82     {
83         scanf("%lld",&a[i]);
84         pos[i]=(i-1)/len+1;
85         s[pos[i]]+=a[i];
86     }
87     scanf("%d",&m);
88     for(int i=1;i<=m;i++)
89     {
90         scanf("%d%d%d",&x,&y,&z);
91         if(y>z)
92             y^=z^=y^=z;
93         if(x==0)
94             update(y,z);
95         else
96             printf("%lld\n",query(y,z));
97     }
98 }
BZOJ 3038

 

posted @ 2017-07-13 21:50  avancent  阅读(131)  评论(0编辑  收藏  举报