首页 > 代码库 > HDU 3308 (线段树区间合并)
HDU 3308 (线段树区间合并)
http://acm.hdu.edu.cn/showproblem.php?pid=3308
题意: 两个操作 : 1 修改 单点 a 处的值。
2 求出 区间【a,b】内的最长上升子序列。
做法:线段树区间合并。了解线段树的具体含义很容易。
1 // by caonima
2 // hehe
3 #include <cstdio>
4 #include <cstring>
5 #include <algorithm>
6 #include <vector>
7 #include <cmath>
8 using namespace std;
9 const int MAX= 1e5+10;
10 int Lsum[MAX<<2],Rsum[MAX<<2],Msum[MAX<<2];
11 int Lnum[MAX<<2],Rnum[MAX<<2];
12 int a[MAX];
13 char Q[10];
14
15 void push_up(int o,int m) {
16 Lsum[o]=Lsum[o<<1];
17 Rsum[o]=Rsum[o<<1|1];
18 Msum[o]=max(Msum[o<<1],Msum[o<<1|1]);
19 Lnum[o]=Lnum[o<<1];
20 Rnum[o]=Rnum[o<<1|1];
21 if(Rnum[o<<1]<Lnum[o<<1|1]) {
22 if(Lsum[o<<1]==(m-(m>>1))) Lsum[o]+=Lsum[o<<1|1];
23 if(Rsum[o<<1|1]==(m>>1)) Rsum[o]+=Rsum[o<<1];
24 Msum[o]=max(Msum[o],Rsum[o<<1]+Lsum[o<<1|1]);
25 }
26 return ;
27 }
28
29 void build(int L,int R,int o) {
30 if(L==R) {
31 Lsum[o]=Rsum[o]=Msum[o]=1;
32 Lnum[o]=Rnum[o]=a[L];
33 return ;
34 }
35 int mid=(L+R)>>1;
36 build(L,mid,o<<1);
37 build(mid+1,R,o<<1|1);
38 push_up(o,R-L+1);
39 }
40
41 void Update(int L,int R,int o,int k,int val) {
42 if(L==R) {
43 Lnum[o]=Rnum[o]=val;
44 // Lsum[o]=Rsum[o]=Msum[o]=1;
45 return ;
46 }
47 int mid=(L+R)>>1;
48 if(k<=mid) Update(L,mid,o<<1,k,val);
49 else Update(mid+1,R,o<<1|1,k,val);
50 push_up(o,R-L+1);
51 }
52
53 int Query(int L,int R,int o,int ls,int rs) {
54 if(ls<=L&&rs>=R) {
55 return Msum[o];
56 }
57 int mid=(L+R)>>1;
58 int ans=0;
59 if(ls<=mid) ans=max(ans,Query(L,mid,o<<1,ls,rs));
60 if(rs>mid) ans=max(ans,Query(mid+1,R,o<<1|1,ls,rs));
61 if(Rnum[o<<1]<Lnum[o<<1|1])
62 ans=max(ans,min(mid-ls+1,Rsum[o<<1])+min(rs-mid,Lsum[o<<1|1]));
63 return ans;
64 }
65
66 int main() {
67 int cas,n,m,ls,rs;
68 scanf("%d",&cas);
69 while(cas--) {
70 scanf("%d %d",&n,&m);
71 for(int i=1;i<=n;i++) scanf("%d",&a[i]);
72 build(1,n,1);
73 for(int i=1;i<=m;i++) {
74 scanf("%s %d %d",Q,&ls,&rs);
75 if(Q[0]==‘Q‘) {
76 int res=Query(1,n,1,ls+1,rs+1);
77 printf("%d\n",res);
78 }
79 else {
80 Update(1,n,1,ls+1,rs);
81 }
82 }
83 }
84 return 0;
2 // hehe
3 #include <cstdio>
4 #include <cstring>
5 #include <algorithm>
6 #include <vector>
7 #include <cmath>
8 using namespace std;
9 const int MAX= 1e5+10;
10 int Lsum[MAX<<2],Rsum[MAX<<2],Msum[MAX<<2];
11 int Lnum[MAX<<2],Rnum[MAX<<2];
12 int a[MAX];
13 char Q[10];
14
15 void push_up(int o,int m) {
16 Lsum[o]=Lsum[o<<1];
17 Rsum[o]=Rsum[o<<1|1];
18 Msum[o]=max(Msum[o<<1],Msum[o<<1|1]);
19 Lnum[o]=Lnum[o<<1];
20 Rnum[o]=Rnum[o<<1|1];
21 if(Rnum[o<<1]<Lnum[o<<1|1]) {
22 if(Lsum[o<<1]==(m-(m>>1))) Lsum[o]+=Lsum[o<<1|1];
23 if(Rsum[o<<1|1]==(m>>1)) Rsum[o]+=Rsum[o<<1];
24 Msum[o]=max(Msum[o],Rsum[o<<1]+Lsum[o<<1|1]);
25 }
26 return ;
27 }
28
29 void build(int L,int R,int o) {
30 if(L==R) {
31 Lsum[o]=Rsum[o]=Msum[o]=1;
32 Lnum[o]=Rnum[o]=a[L];
33 return ;
34 }
35 int mid=(L+R)>>1;
36 build(L,mid,o<<1);
37 build(mid+1,R,o<<1|1);
38 push_up(o,R-L+1);
39 }
40
41 void Update(int L,int R,int o,int k,int val) {
42 if(L==R) {
43 Lnum[o]=Rnum[o]=val;
44 // Lsum[o]=Rsum[o]=Msum[o]=1;
45 return ;
46 }
47 int mid=(L+R)>>1;
48 if(k<=mid) Update(L,mid,o<<1,k,val);
49 else Update(mid+1,R,o<<1|1,k,val);
50 push_up(o,R-L+1);
51 }
52
53 int Query(int L,int R,int o,int ls,int rs) {
54 if(ls<=L&&rs>=R) {
55 return Msum[o];
56 }
57 int mid=(L+R)>>1;
58 int ans=0;
59 if(ls<=mid) ans=max(ans,Query(L,mid,o<<1,ls,rs));
60 if(rs>mid) ans=max(ans,Query(mid+1,R,o<<1|1,ls,rs));
61 if(Rnum[o<<1]<Lnum[o<<1|1])
62 ans=max(ans,min(mid-ls+1,Rsum[o<<1])+min(rs-mid,Lsum[o<<1|1]));
63 return ans;
64 }
65
66 int main() {
67 int cas,n,m,ls,rs;
68 scanf("%d",&cas);
69 while(cas--) {
70 scanf("%d %d",&n,&m);
71 for(int i=1;i<=n;i++) scanf("%d",&a[i]);
72 build(1,n,1);
73 for(int i=1;i<=m;i++) {
74 scanf("%s %d %d",Q,&ls,&rs);
75 if(Q[0]==‘Q‘) {
76 int res=Query(1,n,1,ls+1,rs+1);
77 printf("%d\n",res);
78 }
79 else {
80 Update(1,n,1,ls+1,rs);
81 }
82 }
83 }
84 return 0;
85 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。