线段树训练

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code
 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 }
View Code

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 }
View Code

 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 }
View Code

 

待补

posted @ 2017-08-07 18:22  Elpsywk  阅读(173)  评论(0编辑  收藏  举报