线段树训练
hdu1166,点修改,区间查询sum形式,最简单形式的线段树
1 #include<cstdlib> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=50005; 10 int sum[maxn<<2],a[maxn]; 11 void build(int rt,int l,int r){ 12 if(l==r){ 13 sum[rt]=a[l]; 14 return; 15 } 16 int mid=(l+r)>>1; 17 build(rt<<1, l, mid); 18 build(rt<<1|1, mid+1, r); 19 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 20 } 21 void update(int rt,int l,int r,int p,int c){ 22 if(l==r){ 23 sum[rt]+=c; 24 return; 25 } 26 int mid=(l+r)>>1; 27 if(p<=mid) update(rt<<1, l, mid, p, c); 28 else update(rt<<1|1,mid+1,r, p, c); 29 sum[rt]=sum[rt<<1|1]+sum[rt<<1]; 30 } 31 int query(int rt,int l,int r,int tl,int tr){ 32 if(tl<=l&&tr>=r){ 33 return sum[rt]; 34 } 35 int mid=(l+r)>>1,res=0; 36 if(tl<=mid) res+=query(rt<<1, l, mid, tl, tr); 37 if(tr>mid) res+=query(rt<<1|1, mid+1, r, tl, tr); 38 return res; 39 } 40 int main(){ 41 int t; 42 cin>>t; 43 for(int j=1;j<=t;j++){ 44 int n; 45 cin>>n; 46 for(int i=1;i<=n;i++) cin>>a[i]; 47 build(1, 1, n); 48 cout<<"Case "<<j<<":\n"; 49 string s; 50 while(cin>>s){ 51 if(s[0]=='A'){ 52 int a,b; 53 cin>>a>>b; 54 update(1, 1, n, a, b); 55 } 56 else if(s[0]=='S'){ 57 int a,b; 58 cin>>a>>b; 59 update(1, 1, n, a, -b); 60 } 61 else if(s[0]=='Q'){ 62 int a,b,ans; 63 cin>>a>>b; 64 ans=query(1, 1, n, a,b); 65 cout<<ans<<endl; 66 } 67 else{ 68 break; 69 } 70 } 71 72 } 73 }
hdu1754 点修改,区间查询最大值形式
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=200005; 10 int a[maxn],tree[maxn<<2]; 11 void pushup(int rt){ 12 tree[rt]=max(tree[rt<<1|1],tree[rt<<1]); 13 } 14 void build(int rt,int l,int r){ 15 if(l==r){ 16 tree[rt]=a[l]; 17 return; 18 } 19 int mid=(l+r)>>1; 20 build(rt<<1,l,mid); 21 build(rt<<1|1,mid+1,r); 22 pushup(rt); 23 } 24 25 void update(int rt,int l,int r,int p,int c){ 26 if(l==r){ 27 tree[rt]=c; 28 return; 29 } 30 int mid=(l+r)>>1; 31 if(p<=mid) update(rt<<1, l, mid, p, c); 32 else update(rt<<1|1, mid+1, r, p, c); 33 pushup(rt); 34 } 35 36 int query(int rt,int l,int r,int tl,int tr){ 37 if(tl<=l&&tr>=r){ 38 return tree[rt]; 39 } 40 int mid=(l+r)>>1,res=0; 41 if(tl<=mid) res=max(res,query(rt<<1,l,mid,tl,tr)); 42 if(tr>mid) res=max(query(rt<<1|1,mid+1,r,tl,tr),res); 43 return res; 44 } 45 46 int main(){ 47 int n,m; 48 ios::sync_with_stdio(0); 49 cin.tie(0); 50 cout.tie(0); 51 while(cin>>n>>m){ 52 memset(tree, 0, sizeof tree); 53 memset(a,0,sizeof a); 54 for(int i=1;i<=n;i++) cin>>a[i]; 55 build(1, 1, n); 56 for(int i=0;i<m;i++){ 57 string s; 58 cin>>s; 59 if(s[0]=='Q'){ 60 int a,b; 61 cin>>a>>b; 62 int ans=query(1, 1, n, a, b); 63 cout<<ans<<"\n"; 64 } 65 else if(s[0]=='U'){ 66 int a,b; 67 cin>>a>>b; 68 update(1, 1, n, a, b); 69 } 70 } 71 } 72 73 }
poj3468 区间修改,区间求和,带lazy标记的线段树,会爆int
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=100005; 10 ll a[maxn],sum[maxn<<2],add[maxn<<2]; 11 void pushup(ll rt){ 12 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 13 } 14 void pushdown(ll rt,ll m){ 15 if(add[rt]){ 16 add[rt<<1]+=add[rt]; 17 add[rt<<1|1]+=add[rt]; 18 sum[rt<<1]+=(m-(m>>1))*add[rt]; 19 sum[rt<<1|1]+=(m>>1)*add[rt]; 20 add[rt]=0; 21 } 22 } 23 void build(ll rt,ll l,ll r){ 24 add[rt]=0; 25 if(l==r){ 26 sum[rt]=a[l]; 27 return; 28 } 29 ll mid=(l+r)>>1; 30 build(rt<<1,l,mid); 31 build(rt<<1|1,mid+1,r); 32 pushup(rt); 33 } 34 35 36 void update(ll rt,ll l,ll r,ll tl,ll tr,ll c){ 37 if(tl<=l&&tr>=r){ 38 add[rt]+=c; 39 sum[rt]+=c*(r-l+1); 40 return; 41 } 42 pushdown(rt,r-l+1); 43 ll mid=(l+r)>>1; 44 if(tl<=mid) update(rt<<1, l, mid, tl, tr, c); 45 if(tr>mid) update(rt<<1|1, mid+1, r, tl, tr, c); 46 pushup(rt); 47 } 48 49 50 ll query(ll rt,ll l,ll r,ll tl,ll tr){ 51 if(tl<=l&&tr>=r) return sum[rt]; 52 pushdown(rt, r-l+1); 53 ll mid=(l+r)>>1; 54 ll res=0; 55 if(tl<=mid) res+=query(rt<<1, l, mid, tl, tr); 56 if(tr>mid) res+=query(rt<<1|1, mid+1, r,tl, tr); 57 return res; 58 } 59 60 61 int main(){ 62 ll n,m; 63 ios::sync_with_stdio(0); 64 cin.tie(0); 65 cout.tie(0); 66 cin>>n>>m; 67 for(int i=1;i<=n;i++) cin>>a[i]; 68 build(1, 1, n); 69 for(int i=0;i<m;i++){ 70 string s; 71 ll a,b,c; 72 cin>>s; 73 if(s[0]=='Q'){ 74 cin>>a>>b; 75 ll ans=query(1, 1, n, a, b); 76 cout<<ans<<endl; 77 } 78 else{ 79 cin>>a>>b>>c; 80 update(1, 1, n, a, b, c); 81 } 82 } 83 return 0; 84 }
hdu1698 区间赋值,总区间求和
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=100005; 10 int a[maxn],sum[maxn<<2],add[maxn<<2]; 11 12 void pushdown(int rt,int m){ 13 if(add[rt]){ 14 add[rt<<1]=add[rt]; 15 add[rt<<1|1]=add[rt]; 16 sum[rt<<1]=add[rt]*(m-(m>>1)); 17 sum[rt<<1|1]=add[rt]*(m>>1); 18 add[rt]=0; 19 } 20 } 21 22 void pushup(int rt){ 23 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 24 } 25 26 void build(int rt,int l,int r){ 27 add[rt]=0; 28 if(l==r){ 29 sum[rt]=1; 30 return; 31 } 32 int mid=(l+r)>>1; 33 build(rt<<1,l,mid); 34 build(rt<<1|1, mid+1, r); 35 pushup(rt); 36 } 37 38 void update(int rt,int l,int r,int tl,int tr,int c){ 39 if(tl<=l&&tr>=r){ 40 sum[rt]=c*(r-l+1); 41 add[rt]=c; 42 return; 43 } 44 pushdown(rt, r-l+1); 45 int mid=(l+r)>>1; 46 if(tl<=mid) update(rt<<1,l,mid,tl,tr, c); 47 if(tr>mid) update(rt<<1|1, mid+1, r, tl, tr, c); 48 pushup(rt); 49 } 50 /* 51 int query(int rt,int l,int r,int tl,int tr){ 52 if(tl<=l&&tr>=r){ 53 return sum[rt]; 54 } 55 pushdown(rt,r-l+1); 56 int mid=(l+r)>>1,res=0; 57 if(l<=mid) res+=query(rt,l,mid,tl,tr); 58 if(r>mid) res+=query(rt,mid+1,r,tl,tr); 59 return res; 60 } 61 */ 62 int main(){ 63 ios::sync_with_stdio(0); 64 cin.tie(0); 65 cout.tie(0); 66 int t; 67 cin>>t; 68 for(int i=1;i<=t;i++){ 69 int n,m; 70 cin>>n>>m; 71 build(1, 1, n); 72 for(int j=0;j<m;j++){ 73 int a,b,c; 74 cin>>a>>b>>c; 75 update(1, 1, n, a, b, c); 76 } 77 cout<<"Case "<<i<<": The total value of the hook is "; 78 cout<<sum[1]<<".\n"; 79 } 80 }
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=100005; 10 int a[maxn],sum[maxn<<2],add[maxn<<2]; 11 12 void pushdown(int rt,int m){ 13 if(add[rt]){ 14 add[rt<<1]=add[rt]; 15 add[rt<<1|1]=add[rt]; 16 sum[rt<<1]=add[rt]*(m-(m>>1)); 17 sum[rt<<1|1]=add[rt]*(m>>1); 18 add[rt]=0; 19 } 20 } 21 22 void pushup(int rt){ 23 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 24 } 25 26 void build(int rt,int l,int r){ 27 add[rt]=0; 28 if(l==r){ 29 sum[rt]=1; 30 return; 31 } 32 int mid=(l+r)>>1; 33 build(rt<<1,l,mid); 34 build(rt<<1|1, mid+1, r); 35 pushup(rt); 36 } 37 38 void update(int rt,int l,int r,int tl,int tr,int c){ 39 if(tl<=l&&tr>=r){ 40 sum[rt]=c*(r-l+1); 41 add[rt]=c; 42 return; 43 } 44 pushdown(rt, r-l+1); 45 int mid=(l+r)>>1; 46 if(tl<=mid) update(rt<<1,l,mid,tl,tr, c); 47 if(tr>mid) update(rt<<1|1, mid+1, r, tl, tr, c); 48 pushup(rt); 49 } 50 51 int query(int rt,int l,int r,int tl,int tr){ 52 if(tl<=l&&tr>=r){ 53 return sum[rt]; 54 } 55 pushdown(rt,r-l+1); 56 int mid=(l+r)>>1,res=0; 57 if(tl<=mid) res+=query(rt,l,mid,tl,tr); 58 if(tr>mid) res+=query(rt,mid+1,r,tl,tr); 59 return res; 60 } 61 62 int main(){ 63 ios::sync_with_stdio(0); 64 cin.tie(0); 65 cout.tie(0); 66 int t; 67 cin>>t; 68 for(int i=1;i<=t;i++){ 69 int n,m; 70 cin>>n>>m; 71 build(1, 1, n); 72 for(int j=0;j<m;j++){ 73 int a,b,c; 74 cin>>a>>b>>c; 75 update(1, 1, n, a, b, c); 76 } 77 cout<<"Case "<<i<<": The total value of the hook is "; 78 cout<<query(1, 1, n, 1, 2)<<".\n"; 79 } 80 }
hdu4417 线段树离线处理,求任意区间>某数的个数
1 #include<cstdlib> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=100005; 10 int sum[maxn<<2]; 11 struct nod{ 12 int val; 13 int id; 14 bool operator<(const nod&a)const{ 15 return val<a.val; 16 } 17 }a[maxn]; 18 19 20 void build(int rt,int l,int r){ 21 if(l==r){ 22 sum[rt]=a[l].val; 23 return; 24 } 25 int mid=(l+r)>>1; 26 build(rt<<1, l, mid); 27 build(rt<<1|1, mid+1, r); 28 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 29 } 30 31 32 void update(int rt,int l,int r,int p,int c){ 33 if(l==r){ 34 sum[rt]+=c; 35 return; 36 } 37 int mid=(l+r)>>1; 38 if(p<=mid) update(rt<<1, l, mid, p, c); 39 else update(rt<<1|1,mid+1,r, p, c); 40 sum[rt]=sum[rt<<1|1]+sum[rt<<1]; 41 } 42 43 44 int query(int rt,int l,int r,int tl,int tr){ 45 if(tl<=l&&tr>=r){ 46 return sum[rt]; 47 } 48 int mid=(l+r)>>1,res=0; 49 if(tl<=mid) res+=query(rt<<1, l, mid, tl, tr); 50 if(tr>mid) res+=query(rt<<1|1, mid+1, r, tl, tr); 51 return res; 52 } 53 54 55 struct node{ 56 int l,r,h,id; 57 }q[100005]; 58 bool cmp1(node &a,node &b){ 59 return a.h<b.h; 60 } 61 bool cmp2(node &a,node &b){ 62 return a.id<b.id; 63 } 64 65 int ans[100005]; 66 int main(){ 67 int t; 68 ios::sync_with_stdio(0); 69 cin.tie(0); 70 cout.tie(0); 71 cin>>t; 72 for(int k=1;k<=t;k++){ 73 int n,m; 74 cin>>n>>m; 75 for(int i=1;i<=n;i++) cin>>a[i].val,a[i].id=i; 76 sort(a+1,a+n+1); 77 memset(sum, 0, sizeof sum); 78 for(int i=0;i<m;i++){ 79 cin>>q[i].l>>q[i].r>>q[i].h; 80 q[i].id=i; 81 } 82 sort(q,q+m,cmp1); 83 int tot=1; 84 for(int i=0;i<m;i++){ 85 while(q[i].h>=a[tot].val&&tot<=n){ 86 update(1, 1, n,a[tot].id, 1); 87 tot++; 88 } 89 ans[q[i].id]=query(1, 1, n, q[i].l+1, q[i].r+1); 90 } 91 sort(q,q+m,cmp2); 92 cout<<"Case "<<k<<":\n"; 93 for(int i=0;i<m;i++){ 94 cout<<ans[i]<<"\n"; 95 } 96 } 97 return 0; 98 }
hdu5692 dfs序+线段树,一定注意求和的时候不要乘区间长度,要符合题意。
1 #pragma comment(linker, "/STACK:1024000000,1024000000") ` 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<cmath> 8 #define inf 1e18 9 typedef long long ll; 10 using namespace std; 11 const int maxn=1e5+4; 12 ll head[maxn<<2],in[maxn<<2],out[maxn<<2],cnt,num; 13 ll dis[maxn<<2],b[maxn<<2],va[maxn<<2]; 14 ll sum[maxn<<2],add[maxn<<2]; 15 ll n,m; 16 struct Edge{ 17 ll to,net;//to表示终点,next表示下一条边 18 }edge[maxn<<2]; 19 20 void add_edge(ll u,ll v){ 21 edge[cnt].net=head[u]; 22 edge[cnt].to=v; 23 head[u]=cnt++; 24 } 25 26 void dfs(int u,int fa){ 27 num++; 28 b[num]=dis[u];//? 29 in[u]=num; 30 for(ll i=head[u];i!=-1;i=edge[i].net){ 31 ll v=edge[i].to; 32 if(v!=fa){ 33 dis[v]=dis[u]+va[v]; 34 dfs(v,u); 35 } 36 } 37 out[u]=num; 38 } 39 40 41 42 void pushup(ll rt){ 43 sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); 44 } 45 46 void pushdown(ll rt,ll m){ 47 if(add[rt]){ 48 add[rt<<1]+=add[rt]; 49 add[rt<<1|1]+=add[rt]; 50 sum[rt<<1]+=add[rt]; 51 sum[rt<<1|1]+=add[rt]; 52 add[rt]=0; 53 } 54 } 55 56 void build(ll rt,ll l,ll r){ 57 add[rt]=0; 58 if(l==r){ 59 sum[rt]=b[l]; 60 return; 61 } 62 ll mid=(l+r)>>1; 63 build(rt<<1,l,mid); 64 build(rt<<1|1,mid+1,r); 65 pushup(rt); 66 } 67 68 69 void update(ll rt,ll l,ll r,ll tl,ll tr,ll c){ 70 if(tl<=l&&tr>=r){ 71 add[rt]+=c; 72 sum[rt]+=c;//一定注意这里,每条路径都加,而不是都加,一定注意题意 73 return; 74 } 75 pushdown(rt,r-l+1); 76 ll mid=(l+r)>>1; 77 if(tl<=mid) update(rt<<1, l, mid, tl, tr, c); 78 if(tr>mid) update(rt<<1|1, mid+1, r, tl, tr, c); 79 pushup(rt); 80 } 81 82 83 ll query(ll rt,ll l,ll r,ll tl,ll tr){ 84 if(tl<=l&&tr>=r) return sum[rt]; 85 pushdown(rt, r-l+1); 86 ll mid=(l+r)>>1; 87 ll res=-inf; 88 if(tl<=mid) res=max(res,query(rt<<1, l, mid, tl, tr)); 89 if(tr>mid) res=max(res,query(rt<<1|1, mid+1, r,tl, tr)); 90 return res; 91 } 92 93 94 int main(){ 95 ll t,c,bb,d; 96 ios::sync_with_stdio(0); 97 cin.tie(0); 98 cout.tie(0); 99 cin>>t; 100 for(int k=1;k<=t;k++){ 101 memset(head, -1, sizeof head); 102 memset(sum, 0, sizeof sum); 103 memset(dis, 0, sizeof dis); 104 cout<<"Case #"<<k<<":\n"; 105 num=0; 106 cnt=0; 107 cin>>n>>m; 108 for(int i=1;i<=n-1;i++){ 109 cin>>c>>bb; 110 add_edge(c, bb); 111 add_edge(bb, c); 112 } 113 for(int i=0;i<n;i++) cin>>va[i]; 114 dis[0]=va[0]; 115 dfs(0,-1); 116 build(1, 1, num); 117 for(int i=0;i<m;i++){ 118 cin>>bb; 119 if(bb){ 120 cin>>c; 121 ll ans=query(1, 1, num,in[c], out[c]); 122 cout<<ans<<"\n"; 123 } 124 else{ 125 cin>>c>>d; 126 update(1, 1, num,in[c], out[c],d-va[c]); 127 va[c]=d; 128 } 129 } 130 131 } 132 return 0; 133 }
待补