Can you answer these queries? (线段树
Posted thunder-110
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Can you answer these queries? (线段树相关的知识,希望对你有一定的参考价值。
题意:
初始给你n个数,通过m个操作, 操作0是使区间范围内的每一个a[i]都变成 根号a[i] ,操作1是查询区间范围内数字的和。
思路:
如果一个节点sum[rt]是1的话,根号1还是1,重复遍历这个节点会大大增加计算次数。n和区间左右端点的范围都 <=1e5,所以一个节点最多遍历不超过10次。
如果这个节点sum[rt]是1,那么标记这个节点vis[rt]=1,说明这个节点以后不用往下遍历了。如果一个节点的左右子节点vis[rt<<1]=1, vis[rt<<1|1]==1,那么vis[rt]=1。注意longlong 以及输入要多空一行。
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=1e9+7; const int INF= 0x3f3f3f3f; const int N=1e5+5; ll add[N<<2],sum[N<<2]; ll a[N<<1]; int vis[N<<2]; /* struct node { int v,p; }b[N<<2]; bool cmp(node x,node y) { return x.v<y.v; }*/ void push_up(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1] ; vis[rt] = vis[rt<<1] & vis[rt<<1|1] ; //左右子节点的vis都是1 父节点才是1 } /* void push_down(int rt,int ln ,int rn) { if(add[rt]) { add[rt<<1]=add[rt<<1|1]=add[rt]; sum[rt<<1]=add[rt]*ln; sum[rt<<1|1]=add[rt]*rn; add[rt]=0; } }*/ void Built(int l,int r,int rt) { if(l==r) { sum[rt]=a[l]; if(sum[rt]<=1) vis[rt]=1; return; } int m=l+r>>1; Built(l,m,rt<<1); Built(m+1,r,rt<<1|1); push_up(rt); } void update(int x,int y,int l,int r,int rt) { if(l==r) { sum[rt]= 1LL*sqrt(sum[rt]*1.0); if( sum[rt]<=1 ) vis[rt]=1; return; } int m=l+r>>1; //push_down(rt,m-l+1,r-m); if(x<=m && !vis[rt<<1]) update(x,y,l,m,rt<<1); if(m<y && !vis[rt<<1|1]) update(x,y,m+1,r,rt<<1|1); push_up(rt); } ll Query(int x,int y, int l,int r,int rt) { if(x<=l && r<=y) { return sum[rt]; } int m=l+r>>1; //push_down(rt,m-l+1,r-m); ll ans=0; if(x<=m) ans+=Query(x,y,l,m,rt<<1); if(m<y) ans+=Query(x,y,m+1,r,rt<<1|1); return ans; } int main() { int x,y,c=0,n,m,q; while(~scanf("%d",&n) ) { /*for(int i=1;i<=n;i++) scanf("%d",&b[i].v),b[i].p=i; sort(b+1,b+1+n,cmp); int cnt=0; for(int i=1;i<=n;i++) { if(b[i].v != b[i-1].v) cnt++; a[b[i].p]=cnt; }//离散化完毕 */ for(int i=1;i<=n;i++) scanf("%lld",&a[i]); mem(vis,0); mem(sum,0); Built(1,n,1); scanf("%d",&m); printf("Case #%d: ",++c); while(m--) { scanf("%d%d%d",&q,&x,&y); if(x>y) swap(x,y); if(q==0) update(x,y,1,n,1); else printf("%lld ",Query(x,y,1,n,1) ); } cout<<endl; } }
以上是关于Can you answer these queries? (线段树的主要内容,如果未能解决你的问题,请参考以下文章
HDU4027 Can you answer these queries? —— 线段树 区间修改
HDU-Can you answer these queries? (线段树+区间修改)
HDU4027 Can you answer these queries?
HDU 1027 G - Can you answer these queries?