2019年第二阶段我要变强个人训练赛第八场 B.序列(seq)
B.序列(seq)
•题目描述
给出一个长度为n的序列a,每次对序列进行一下的某一个操作。
•输入
第一行两个整数n,q表示序列长度和操作个数。
接下来一行n个数,表示序列a。
接下来q行表示操作,其格式见题目描述。
•输出
见题目描述。
•题解
单点修改区间查询,但是坑点在于单点修改超时,如果一个值小于等于1开根不受影响,所以可以不去耗时间修改它;具体实现方法就是叶子节点定义一个变量f代表是否需要修改如果小于等于1就不需要然后向上传递p=p<<1&p<<1|1就行了;•AC代码
View Code1 #include <bits/stdc++.h> 2 using namespace std; 3 struct node 4 { 5 int l,r,f; 6 long long v; 7 }t[400005]; 8 long long a[100005]; 9 void build(int p,int l,int r) 10 { 11 t[p].l=l; 12 t[p].r=r; 13 t[p].f=0; 14 if(l==r) 15 { 16 t[p].v=a[l]; 17 return; 18 } 19 int mid=(l+r)>>1; 20 build(p<<1,l,mid); 21 build(p<<1|1,mid+1,r); 22 t[p].v=t[p<<1].v+t[p<<1|1].v; 23 t[p].f=t[p<<1].f&t[p<<1|1].f; 24 } 25 void change(int p,int x,int y) 26 { 27 if(t[p].l==t[p].r) 28 { 29 t[p].v=sqrt(t[p].v); 30 if(t[p].v<=1) 31 t[p].f=1; 32 return; 33 } 34 int mid=(t[p].l+t[p].r)>>1; 35 if(x<=mid&&!t[p<<1].f) 36 change(p<<1,x,y); 37 if(y>mid&&!t[p<<1|1].f) 38 change(p<<1|1,x,y); 39 t[p].v=t[p<<1].v+t[p<<1|1].v; 40 t[p].f=t[p<<1].f&t[p<<1|1].f; 41 } 42 long long sum(int p,int x,int y) 43 { 44 if(x<=t[p].l&&y>=t[p].r) 45 return t[p].v; 46 int mid=(t[p].l+t[p].r)>>1; 47 long long ans=0; 48 if(x<=mid) 49 ans+=sum(p<<1,x,y); 50 if(y>mid) 51 ans+=sum(p<<1|1,x,y); 52 return ans; 53 } 54 int main() 55 { 56 int n,m; 57 scanf("%d%d",&n,&m); 58 for(int i=1;i<=n;i++) 59 scanf("%lld",&a[i]); 60 build(1,1,n); 61 while(m--) 62 { 63 int a,b,c; 64 scanf("%d%d%d",&a,&b,&c); 65 if(a==1) 66 printf("%lld\n",sum(1,b,c)); 67 else 68 change(1,b,c); 69 } 70 }
•题解来源(by mhr)