数据结构--线段树
线段树 好久没做全部忘记了 还得重新学一下了
线段树--单点更新
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 }
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 }
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 }
代码有时间补上
题意:
思路:
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 }
题意:给一个数组 再给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 }
题意:给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 }
题意:给你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 }
题意:给你一个字符串 求l,r区间内字符串的哈希值,哈希公式为 H(s)=∏i≤len(s)i=1(Si−28) (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 }
线段树+区间离散化(校赛的一个题目)
POJ2528
POJ3225