数据结构--线段树

线段树 好久没做全部忘记了 还得重新学一下了

线段树--单点更新

HUD1166

题意:中文题

思路:线段树的单点更新

AC代码

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define mem(a) memset(a,0,sizeof(a))
14 using namespace std;
15 
16 struct Node{
17     int l,r;
18     int sum;
19 };
20 Node Tree[100000<<2];
21 
22 void Build_Tree(int root, int l, int r)
23 {
24     Tree[root].l=l;
25     Tree[root].r=r;
26     if(l==r)
27     {
28         scanf("%d",&Tree[root].sum);
29         return;
30     }
31     int mid=l+r>>1;
32     Build_Tree(root*2+1,l,mid);
33     Build_Tree(root*2+2,mid+1,r);
34     Tree[root].sum=Tree[root*2+1].sum+Tree[root*2+2].sum;
35 }
36 
37 int Query(int root,int l,int r)
38 {
39     if(Tree[root].l==l && Tree[root].r==r)
40         return Tree[root].sum;
41     int mid=Tree[root].l+Tree[root].r>>1;
42     if(r<=mid)
43         return Query(root*2+1,l,r);
44     if(l>mid)
45         return Query(root*2+2,l,r);
46     else
47         return Query(root*2+1,l,mid)+Query(root*2+2,mid+1,r);
48 }
49 
50 void Update_One(int root,int l,int r,int p,int add)
51 {
52     if(l==r)
53     {
54         Tree[root].sum += add;
55         return;
56     }
57     int mid=l+r>>1;
58     if(p<=mid)  Update_One(root*2+1,l,mid,p,add);
59     else Update_One(root*2+2,mid+1,r,p,add);
60     Tree[root].sum=Tree[root*2+1].sum + Tree[root*2+2].sum;
61 }
62 
63 int main()
64 {
65     int t,c=0,n,l,r;
66     string s;
67     scanf("%d",&t);
68     while(t--){
69             printf("Case %d:\n",++c);
70         scanf("%d",&n);
71         mem(Tree);
72         Build_Tree(0,0,n-1);
73         while(cin>>s&&s!="End")
74         {
75             scanf("%d%d",&l,&r);
76             if(s=="Query")  printf("%d\n",Query(0,l-1,r-1));
77             else if(s=="Add")  Update_One(0,0,n-1,l-1,r);
78             else Update_One(0,0,n-1,l-1,-r);
79         }
80     }
81    return 0;
82 }
View Code

 HDU1754

题意:中文题

思路:线段树的单点更新

AC代码

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define mem(a) memset(a,0,sizeof(a))
14 using namespace std;
15 
16 struct Node{
17     int l,r;
18     int m;
19 };
20 
21 int date,p;
22 Node Tree[222222<<2];
23 
24 void Build_Tree(int root, int l, int r)
25 {
26     Tree[root].l=l;
27     Tree[root].r=r;
28     if(l==r)
29     {
30         scanf("%d",&Tree[root].m);
31         return;
32     }
33     int mid=l+r>>1;
34     Build_Tree(root*2,l,mid);
35     Build_Tree(root*2+1,mid+1,r);
36     Tree[root].m = max(Tree[root*2].m,Tree[root*2+1].m);
37 }
38 
39 int Query(int root, int l, int r)
40 {
41     if(Tree[root].l==l && Tree[root].r==r)
42         return Tree[root].m;
43     int mid=Tree[root].l+Tree[root].r>>1;
44     if(r<=mid)
45         return Query(root*2,l,r);
46     if(l>mid)
47         return Query(root*2+1,l,r);
48     else
49         return max(Query(root*2,l,mid),Query(root*2+1,mid+1,r));
50 }
51 
52 void Update_One(int root,int l,int r)
53 {
54     if(l==r)
55     {
56         Tree[root].m=date;
57         return;
58     }
59     int mid=l+r>>1;
60     if(p<=mid)  Update_One(root*2,l,mid);
61     else  Update_One(root*2+1,mid+1,r);
62     Tree[root].m = max(Tree[root*2].m,Tree[root*2+1].m);
63 }
64 
65 int main()
66 {
67     int n,q,l,r;
68     char c;
69     while(~scanf("%d%d",&n,&q)){
70         Build_Tree(1,1,n);
71         while(q--){
72             getchar();
73             scanf("%c%d%d",&c,&l,&r);
74             if(c=='Q')  printf("%d\n",Query(1,l,r));
75             else  {p=l,date=r;Update_One(1,1,n);}
76         }
77     }
78    return 0;
79 }
View Code

HUD1556

题意:输入n 然后n个区间操作 l,r 对区间的气球涂油漆 ,最后输出每个气球被涂了多少次

思路:线段树的区间更新

AC代码

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define lson l,mid,rt<<1
14 #define rson mid+1,r,rt<<1|1
15 #define len (Tr[rt].r-Tr[rt].l+1)
16 #define mem(a) memset(a,0,sizeof(a))
17 using namespace std;
18 
19 struct Node{
20     int l,r;
21     int v,add;
22 };
23 Node Tr[200005<<2];
24 
25 void Push_up(int rt){
26     Tr[rt].v=Tr[rt<<1].v+Tr[rt<<1|1].v;
27 }
28 
29 void Push_Down(int rt, int m){
30     Tr[rt<<1].add+=Tr[rt].add;
31     Tr[rt<<1|1].add+=Tr[rt].add;
32     Tr[rt<<1].v+=Tr[rt].add*(m-(m>>1));
33     Tr[rt<<1|1].v+=Tr[rt].add*(m>>1);
34     Tr[rt].add=0;
35 }
36 
37 void Build_Tree(int l,int r,int rt){
38     Tr[rt].l=l,Tr[rt].r=r;
39     if(l==r) return;
40     int mid=l+r>>1;
41     Build_Tree(lson);
42     Build_Tree(rson);
43     Push_up(rt);
44 }
45 
46 void Updata(int l,int r,int rt){
47     if(l==Tr[rt].l && r==Tr[rt].r){
48         Tr[rt].v+=len;
49         Tr[rt].add++;
50         return;
51     }
52     int mid=Tr[rt].l+Tr[rt].r>>1;
53     if(r<=mid) Updata(l,r,rt<<1);
54     else if(l>mid) Updata(l,r,rt<<1|1);
55     else{
56         Updata(lson);
57         Updata(rson);
58     }
59     Push_up(rt);
60 }
61 
62 int Query(int l,int r,int rt){
63     if(l==Tr[rt].l && r==Tr[rt].r) return Tr[rt].v;
64     if(Tr[rt].add!=0) Push_Down(rt,len);
65     int mid=Tr[rt].l+Tr[rt].r>>1;
66     if(r<=mid) return Query(l,r,rt<<1);
67     if(l>mid) return Query(l,r,rt<<1|1);
68     else return Query(l,mid,rt<<1)+Query(mid+1,r,rt<<1|1);
69 }
70 
71 int main(){
72     int n,q,l,r;
73     while(scanf("%d",&n) && n!=0){
74         mem(Tr);
75         Build_Tree(1,n,1);
76         q=n;
77         while(q--){
78             scanf("%d%d",&l,&r);
79             Updata(l,r,1);
80         }
81         for(int i=1; i<=n; i++){
82             if(i!=1) printf(" ");
83             printf("%d",Query(i,i,1));
84         }
85         printf("\n");
86     }
87     return 0;
88 }
View Code

代码有时间补上

HDU1394

HDU2795

题意:

思路:

 AC代码

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define lson l,mid,rt<<1
14 #define rson mid+1,r,rt<<1|1
15 #define len (Tr[rt].r-Tr[rt].l+1)
16 #define mem(a) memset(a,0,sizeof(a))
17 using namespace std;
18 const int N=200005;
19 struct Node{
20     int l,r;
21     int maxn;
22 }Tr[N<<2];
23 int w,ans[N];
24 
25 void Push_up(int rt){
26     Tr[rt].maxn=max(Tr[rt<<1].maxn,Tr[rt<<1|1].maxn);
27 }
28 
29 void Build_Tree(int l, int r, int rt){
30     Tr[rt].l=l,Tr[rt].r=r;
31     if(l==r){
32         Tr[rt].maxn=w; return;
33     }
34     int mid=l+r>>1;
35     Build_Tree(lson);
36     Build_Tree(rson);
37     Push_up(rt);
38 }
39 
40 void Updata_One(int l,int r,int rt,int data,int n){
41     int mid=l+r>>1;
42     if(Tr[rt].maxn<data) {ans[n]=-1;return;}
43     else if(l==r){
44         Tr[rt].maxn-=data;
45        ans[n]=Tr[rt].l;
46        return;
47     }
48     else if(Tr[rt<<1].maxn>=data)
49         Updata_One(lson,data,n);
50     else if(Tr[rt<<1|1].maxn>=data)
51         Updata_One(rson,data,n);
52     Push_up(rt);
53 }
54 
55 int main(){
56     int h,n,x;
57     while(scanf("%d%d%d",&h,&w,&n)!=EOF){
58         mem(Tr),mem(ans);
59         h = h < N ? h : N;
60         Build_Tree(1,h,1);
61         for(int i=1; i<=n; i++){
62             scanf("%d",&x);
63             Updata_One(1,h,1,x,i); printf("%d\n",ans[i]);
64         }
65     }
66    return 0;
67 }
View Code

HDU1698

题意:给一个数组 再给Q个操作 每次将x y区间内的数换成z 求最后数组的和

思路:线段树的区间替换

AC代码

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define lson l,mid,rt<<1
14 #define rson mid+1,r,rt<<1|1
15 #define len (Tr[rt].r-Tr[rt].l+1)
16 #define mem(a) memset(a,0,sizeof(a))
17 using namespace std;
18 
19 struct Node{
20     int l,r;
21     int val;
22     int lazy;
23 };
24 
25 Node Tr[100000<<2];
26 
27 void Push_up(int rt){
28     Tr[rt].val=Tr[rt<<1].val+Tr[rt<<1|1].val;
29 }
30 
31 void Push_Down(int rt,int m){
32     Tr[rt<<1].lazy=Tr[rt<<1|1].lazy=Tr[rt].lazy;
33     Tr[rt<<1].val=Tr[rt].lazy*(m-(m>>1));
34     Tr[rt<<1|1].val=Tr[rt].lazy*(m>>1);
35     Tr[rt].lazy=0;
36 }
37 
38 void Build(int l, int r, int rt){
39     Tr[rt].l=l;
40     Tr[rt].r=r;
41     if(l==r) {Tr[rt].val=1;return;}
42     int mid=l+r>>1;
43     Build(lson);
44     Build(rson);
45     Push_up(rt);
46 }
47 
48 void Updata(int l,int r,int rt,int data){
49     if(Tr[rt].l==l && Tr[rt].r==r){
50         Tr[rt].lazy=data;
51         Tr[rt].val=data*len;
52         return;
53     }
54     if (Tr[rt].lazy) Push_Down(rt,len);
55     int mid=Tr[rt].l+Tr[rt].r>>1; //printf("%d pp\n",mid);
56     if(r<=mid) Updata(l,r,rt<<1,data);
57     else if(l>mid) Updata(l,r,rt<<1|1,data);
58     else {Updata(lson,data);Updata(rson,data);}
59     Push_up(rt);
60 }
61 
62 int main()
63 {
64     int t,n,m,l,r,data,T=0;
65     scanf("%d",&t);
66     while(t--){
67         mem(Tr);
68         scanf("%d",&n);
69         Build(1,n,1);
70         scanf("%d",&m);
71         while(m--){
72             scanf("%d%d%d",&l,&r,&data);
73             Updata(l,r,1,data);
74         }
75         printf("Case %d: The total value of the hook is %d.\n",++T,Tr[1].val);
76     }
77    return 0;
78 }
View Code

POJ2828

POJ2886

POJ3468

题意:给n个数 然后Q个操作,Q代表查询区间a,b的和,C表示对区间a,b内的每个数加c

思路:线段树区间更新 lazy思想 在更新的时候特别注意,一定要统一思想,比如lazy用于记录的是孩子节点的增量 不要重复增加sum 不要重复增加 逻辑要正确

AC代码 

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define lson l,mid,rt<<1
14 #define rson mid+1,r,rt<<1|1
15 #define len (Tr[rt].r-Tr[rt].l+1)
16 #define mem(a) memset(a,0,sizeof(a))
17 using namespace std;
18 struct Node{
19     ll l,r;
20     ll sum,add;
21 }Tr[100000<<2];
22 
23 void Push_up(ll rt){
24     Tr[rt].sum=Tr[rt<<1].sum + Tr[rt<<1|1].sum;
25 }
26 
27 void Push_down(ll rt, ll m){
28     Tr[rt<<1].add+=Tr[rt].add;
29     Tr[rt<<1|1].add+=Tr[rt].add;
30     Tr[rt<<1].sum+=Tr[rt].add*(m-(m>>1));
31     Tr[rt<<1|1].sum+=Tr[rt].add*(m>>1);
32     Tr[rt].add=0;
33 }
34 
35 void Build_Tree(ll l, ll r, ll rt){
36     Tr[rt].l=l, Tr[rt].r=r;
37     if(l==r){
38         scanf("%lld",&Tr[rt].sum);
39         return;
40     }
41     ll mid=l+r>>1;
42     Build_Tree(lson);
43     Build_Tree(rson);
44     Push_up(rt);
45 }
46 
47 void Updata(ll l, ll r, ll rt, ll data){
48     if(l==Tr[rt].l && r==Tr[rt].r){
49         Tr[rt].sum+=data*len;
50         Tr[rt].add+=data;
51         return;
52     }
53     if(Tr[rt].add) Push_down(rt,len);
54     ll mid = Tr[rt].l+Tr[rt].r>>1;
55     if(r<=mid) Updata(l,r,rt<<1,data);
56     else if(l>mid) Updata(l,r,rt<<1|1,data);
57     else{
58         Updata(lson,data);
59         Updata(rson,data);
60     }
61     Push_up(rt);
62 }
63 
64 ll Query(ll l, ll r, ll rt){
65     if(Tr[rt].l==l && Tr[rt].r==r)
66         return Tr[rt].sum;
67     if(Tr[rt].add) Push_down(rt,len);
68     ll mid=Tr[rt].l+Tr[rt].r>>1;
69     if(r<=mid) return Query(l,r,rt<<1);
70     if(l>mid) return Query(l,r,rt<<1|1);
71     else return Query(lson) + Query(rson);
72 }
73 
74 int  main(){
75     ll n,q,l,r,c;
76     char s;
77     while(cin>>n>>q){
78         mem(Tr);
79         Build_Tree(1,n,1);
80         while(q--){
81         cin>>s;
82         if(s=='Q'){
83             scanf("%lld%lld",&l,&r);
84             ll ans=Query(l,r,1);
85             printf("%lld\n",ans);
86         }
87         if(s=='C'){
88             scanf("%lld%lld%lld",&l,&r,&c);
89             Updata(l,r,1,c);
90         }
91         }
92     }
93     return 0;
94 }
View Code

POJ3264

题意:给你n个数 然后q个查询 查询区间l,r内最大值与最小值的差

思路:区间查询 连更新都不用这里可以用分别用一个变量来存查询区间的最大最小值 省去了每次要查询最大最小各一次 我在这里直接用maxn[0] minn[0]

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define lson l,mid,rt<<1
14 #define rson mid+1,r,rt<<1|1
15 #define mem(a) memset(a,0,sizeof(a))
16 using namespace std;
17 
18 ///poj3264
19 const int N=50000;
20 int maxn[N<<2];
21 int minn[N<<2];
22 
23 void Push_up(int rt){
24     maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
25     minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
26 }
27 
28 void Build(int l, int r, int rt){
29     if(l==r){
30         int vv;
31         scanf("%d",&vv);
32         maxn[rt]=minn[rt]=vv;
33         return;
34     }
35     int mid=l+r>>1;
36     Build(lson);
37     Build(rson);
38     Push_up(rt);
39 }
40 
41 void Query(int l,int r,int rt,int L, int R){
42     if(l==L && r==R){
43         maxn[0]=max(maxn[0],maxn[rt]);
44         minn[0]=min(minn[0],minn[rt]);
45         return;
46     }
47     int mid=L+R>>1;
48     if(r<=mid) Query(l,r,rt<<1,L,mid);
49     else if(l>mid) Query(l,r,rt<<1|1,mid+1,R);
50     else Query(lson,L,mid),Query(rson,mid+1,R);
51 }
52 
53 int main(){
54     int n,q,l,r;
55     while(scanf("%d%d",&n,&q)!=EOF){
56         Build(1,n,1);
57         while(q--){
58             maxn[0]=0,minn[0]=99999999;
59             scanf("%d%d",&l,&r);
60             Query(l,r,1,1,n);
61             printf("%d\n",maxn[0]-minn[0]);
62         }
63     }
64     return 0;
65 }
View Code

 

 

 

 HDU5685

题意:给你一个字符串 求l,r区间内字符串的哈希值,哈希公式为 H(s)=ilen(s)i=1(Si28) (mod 9973)

思路:线段树查找 不需要更新

AC代码:

 1 #include "iostream"
 2 #include "string.h"
 3 #include "stack"
 4 #include "queue"
 5 #include "string"
 6 #include "vector"
 7 #include "set"
 8 #include "map"
 9 #include "algorithm"
10 #include "stdio.h"
11 #include "math.h"
12 #define ll long long
13 #define lson l,mid,rt<<1
14 #define rson mid+1,r,rt<<1|1
15 #define mem(a) memset(a,0,sizeof(a))
16 using namespace std;
17 const int mod=9973;
18 struct Node{
19     int l,r;
20     int s;
21 };
22 Node Tr[100005<<2];
23 char ss[100005];
24 void Push_up(int rt){
25     Tr[rt].s=(Tr[rt<<1].s*Tr[rt<<1|1].s)%mod;
26 }
27 
28 void Build(int l,int r, int rt){
29     Tr[rt].l=l,Tr[rt].r=r;
30     if(l==r){
31         Tr[rt].s=ss[l-1]-28;
32         return;
33     }
34     int mid=l+r>>1;
35     Build(lson);
36     Build(rson);
37     Push_up(rt);
38 }
39 
40 int Query(int l, int r, int rt){
41     if(Tr[rt].l==l && Tr[rt].r==r)
42         return Tr[rt].s;
43     int mid=Tr[rt].l+Tr[rt].r>>1;
44     if(r<=mid) return Query(l,r,rt<<1);
45     if(l>mid) return Query(l,r,rt<<1|1);
46     else return Query(lson)*Query(rson)%mod;
47 }
48 
49 int main()
50 {
51     int n,l,r;
52     while(cin>>n){
53         mem(ss),mem(Tr);
54         cin>>ss;
55         int len=strlen(ss);
56         Build(1,len,1);
57         while(n--){
58             scanf("%d%d",&l,&r);
59             cout<<Query(l,r,1)%mod<<endl;
60         }
61     }
62     return 0;
63 }
View Code

线段树+区间离散化(校赛的一个题目)

POJ2528

POJ3225

POJ1436

POJ2991

POJ3667

 

posted on 2016-11-04 00:58  lazzzy  阅读(185)  评论(0编辑  收藏  举报

导航