线段树
Posted zxz666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树相关的知识,希望对你有一定的参考价值。
题目:hdu 5239
http://acm.hdu.edu.cn/showproblem.php?pid=5239
这是一个典型的线段树模板,里面的取模很强,mod=9223372034707292160. 这个膜是2的64次方减掉2的32次方的值,某一个数连续平方取模若干以后值不变,这个题就是用这个膜的性质去解决这个问题的,如果不这样操作的话会T的,大概进行29次的平方以后不会变了,使用用一个数组标记该节点,如果该节点被标记了,在更新的时候,就不需要向下更新了,节省非常多的时间了。
1 #include<bits/stdc++.h> 2 typedef unsigned long long ll; 3 using namespace std; 4 ll s[100503<<2]; 5 ll sum[100503<<2]; 6 int b[100503<<2]; 7 void pushup(int p) 8 { 9 sum[p]=(sum[p<<1]+sum[p<<1|1])%mod; 10 b[p]=b[p<<1]&b[p<<1|1]; 11 } 12 void build(int p,int l,int r) 13 { 14 if(l==r) 15 { 16 sum[p]=s[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 pushup(p); 23 } 24 ll look(int x,int y,int p,int l,int r) 25 { ll ss=0; 26 if(x<=l&&r<=y) 27 { 28 return sum[p]; 29 } 30 int mid=(l+r)>>1; 31 if(x<=mid)ss=(ss+look(x,y,p<<1,l,mid))%mod; 32 if(y>mid) ss=(ss+look(x,y,p<<1|1,mid+1,r))%mod; 33 return ss; 34 } 35 ll kc(ll a,ll b) 36 { 37 ll c=0; 38 while(b) 39 { 40 if(b&1)c=(a+c)%mod; 41 a=(a+a)%mod; 42 b>>=1; 43 }return c; 44 } 45 void add(int x,int y,int p,int l,int r) 46 { if(b[p]&&x<=l&&r<=y) 47 return ; 48 if(l==r) 49 { 50 ll team=kc(sum[p],sum[p]); 51 if(team==sum[p])b[p]=1; 52 sum[p]=team; 53 return ; 54 } 55 int mid=(l+r)>>1; 56 if(x<=mid) add(x,y,p<<1,l,mid); 57 if(y>mid)add(x,y,p<<1|1,mid+1,r); 58 pushup(p); 59 } 60 ll S; 61 int main() 62 { 63 int t; 64 cin>>t; 65 for(int i=1;i<=t;i++) 66 {S=0;mem(b);mem(s);mem(sum); 67 printf("Case #%d: ",i); 68 ll n,m; 69 sll(n,m); 70 for(int j=1;j<=n;j++) 71 sl(s[j]); 72 build(1,1,n); 73 while(m--) 74 { 75 int x,y; 76 sii(x,y); 77 S=(S+look(x,y,1,1,n))%mod; 78 printf("%lld ",S); 79 add(x,y,1,1,n); 80 } 81 } 82 }
以上是关于线段树的主要内容,如果未能解决你的问题,请参考以下文章