Bzoj3038 上帝造题的七分钟2 线段树

 

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1135  Solved: 509

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,谢谢!

 

Source

 

上一篇博http://www.cnblogs.com/SilverNebula/p/5994730.html 写了并查集解法。

实际上刚看到题的时候,我想到的是用线段树正面刚。

 

线段树上加一个标记,维护已经变成1的连续区间,之后的开方都跳过1区间。剩下的就是区间求和。

比并查集快了100+ms (也可能是我并查集解法写得不好)2333

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #define ls l,mid,rt<<1
 8 #define rs mid+1,r,rt<<1|1
 9 using namespace std;
10 const int mxn=100010;
11 int read(){
12     int x=0,f=1;char ch=getchar();
13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 long long read1(){
18     long long x=0,f=1;char ch=getchar();
19     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
20     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
21     return x*f;
22 }
23 int n,m;
24 long long data[mxn];
25 struct node{
26     long long num;
27     bool one;
28 }t[mxn<<2];
29 void Build(int l,int r,int rt){
30     if(l==r){
31         t[rt].num=data[l];
32         if(data[l]==1)t[rt].one=1;
33         else t[rt].one=0;
34         return;
35     }
36     int mid=(l+r)>>1;
37     Build(ls);Build(rs);
38     t[rt].one=(t[rt<<1].one&t[rt<<1|1].one);
39     t[rt].num=t[rt<<1].num+t[rt<<1|1].num;
40     return;
41 }
42 void change(int L,int R,int l,int r,int rt){
43     if(l==r && L<=l && r<=R){
44         t[rt].num=sqrt(t[rt].num);
45         if(t[rt].num==1) t[rt].one=1;
46         return;
47     }
48     int mid=(l+r)>>1;
49     if(L<=mid && !t[rt<<1].one)change(L,R,ls);
50     if(R>mid && !t[rt<<1|1].one)change(L,R,rs);
51     if(t[rt<<1].one && t[rt<<1|1].one) t[rt].one=1;
52     t[rt].num=t[rt<<1].num+t[rt<<1|1].num;
53     return;
54 }
55 long long smm(int L,int R,int l,int r,int rt){
56     if(L<=l && r<=R){
57         return t[rt].num; 
58     }
59     long long res=0;
60     int mid=(l+r)>>1;
61     if(L<=mid)res+=smm(L,R,ls);
62     if(R>mid)res+=smm(L,R,rs);
63     return res;
64 }
65 int op;
66 int main(){
67 //    freopen("ship.in","r",stdin);
68 //    freopen("ship.out","w",stdout);
69     n=read();
70 //    m=read();
71     int i,j;
72     for(i=1;i<=n;i++){
73         data[i]=read1();
74     }
75     Build(1,n,1);
76     m=read();
77     int x,y;
78     while(m--){
79         op=read();x=read();y=read();
80         if(x>y)swap(x,y);
81         if(op==0){
82             change(x,y,1,n,1);
83         }
84         else{
85             long long ans=smm(x,y,1,n,1);
86             printf("%lld\n",ans);
87         }
88     }
89     return 0;
90 }

 

posted @ 2016-10-24 21:39  SilverNebula  阅读(132)  评论(0编辑  收藏  举报
AmazingCounters.com