【HDOJ】【1754】I Hate It

线段树



  这是一道线段树的裸题……带单点修改的RMQ

  为什么我会想到写这么一道傻逼题呢?是因为这样……

  我很好奇那个突然冒出来的黄色箭头是什么……所以就去切了一下这道水题……

  

  毫无压力地快速敲完……突然萌生了一种想法:试试自底向上线段树!

  重新看了下zkw大牛的《统计的力量》,发现确实好写,而且灰常好用!

写的时候出现的问题:读入应该是读到[n+1,n+n]这一段,而我读到了[n+i-1,n+n-1]……(也就是说:1~n格是树中节点,后n个格是叶子节点)

 1 int t[N<<2],a[N];
 2 #define L (o<<1)
 3 #define R (o<<1|1)
 4 #define mid (l+r>>1)
 5 void maintain(int o,int l,int r){
 6     if (l<r) t[o]=max(t[L],t[R]);
 7 }
 8 void build(int o,int l,int r){
 9     if (l==r) t[o]=a[l];
10     else{
11         build(L,l,mid);
12         build(R,mid+1,r);
13         maintain(o,l,r);
14     }
15 }
16 void update(int o,int l,int r,int pos,int v){
17     if (l==r) t[o]=v;
18     else{
19         if (pos<=mid) update(L,l,mid,pos,v);
20         else update(R,mid+1,r,pos,v);
21         maintain(o,l,r);
22     }
23 }
24 int ql,qr,ans;
25 void query(int o,int l,int r){
26     if (ql<=l && qr>=r)    ans=max(ans,t[o]);
27     else{
28         if (ql<=mid) query(L,l,mid);
29         if (qr>mid) query(R,mid+1,r);
30     }
31 }

普通线段树

 1 int t[N<<2],n,m;
 2 void update(int p,int v){
 3     for(t[p+=n]=v,p>>=1;p;p>>=1)
 4         t[p]=max(t[p+p],t[p+p^1]);
 5 }
 6 int ans;
 7 void query(int l,int r){
 8     for(l=l+n-1,r=r+n+1;l^r^1;l>>=1,r>>=1){
 9         if (!(l&1)) ans=max(t[l^1],ans);
10         if ( r&1) ans=max(t[r^1],ans);
11     }
12 }

zkw线段树

完整代码:(确实快了好多!而且代码短了好多……)

 1 //HDOJ 1754
 2 #include<cmath>
 3 #include<vector>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define rep(i,n) for(int i=0;i<n;++i)
10 #define F(i,j,n) for(int i=j;i<=n;++i)
11 #define D(i,j,n) for(int i=j;i>=n;--i)
12 #define pb push_back
13 #define CC(a,b) memset(a,b,sizeof(a))
14 using namespace std;
15 int getint(){
16     int v=0,sign=1; char ch=getchar();
17     while(!isdigit(ch)) {if(ch==‘-‘) sign=-1; ch=getchar();}
18     while(isdigit(ch))  {v=v*10+ch-‘0‘; ch=getchar();}
19     return v*sign;
20 }
21 const int N=200010,INF=~0u>>2;
22 const double eps=1e-8;
23 /*******************template********************/
24
25 int t[N<<2],a[N],cnt;
26 #define L (o<<1)
27 #define R (o<<1|1)
28 #define mid (l+r>>1)
29 void maintain(int o,int l,int r){
30     if (l<r) t[o]=max(t[L],t[R]);
31 }
32
33 void build(int o,int l,int r){
34     if (l==r) t[o]=a[l];
35     else{
36         build(L,l,mid);
37         build(R,mid+1,r);
38         maintain(o,l,r);
39     }
40 }
41 void update(int o,int l,int r,int pos,int v){
42     if (l==r) t[o]=v;
43     else{
44         if (pos<=mid) update(L,l,mid,pos,v);
45         else update(R,mid+1,r,pos,v);
46         maintain(o,l,r);
47     }
48 }
49 int ql,qr,ans;
50 void query(int o,int l,int r){
51     if (ql<=l && qr>=r)    ans=max(ans,t[o]);
52     else{
53         if (ql<=mid) query(L,l,mid);
54         if (qr>mid) query(R,mid+1,r);
55     }
56 }
57 int main(){
58 #ifndef ONLINE_JUDGE
59     freopen("input.txt","r",stdin);
60 //    freopen("output.txt","w",stdout);
61 #endif
62     int n,m;
63     while(scanf("%d%d",&n,&m)!=EOF){
64         F(i,1,n) a[i]=getint();
65         build(1,1,n);
66         char s[4];
67         F(i,1,m){
68             scanf("%s",s); ql=getint(); qr=getint();
69             if (s[0]==‘Q‘) {ans=0; query(1,1,n); printf("%d\n",ans);}
70             if (s[0]==‘U‘) update(1,1,n,ql,qr);
71         }
72     }
73     return 0;
74 }

普通线段树(436MS 3996K)

 1 //HDOJ 1754
 2 #include<cmath>
 3 #include<vector>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define rep(i,n) for(int i=0;i<n;++i)
10 #define F(i,j,n) for(int i=j;i<=n;++i)
11 #define D(i,j,n) for(int i=j;i>=n;--i)
12 #define pb push_back
13 #define CC(a,b) memset(a,b,sizeof(a))
14 using namespace std;
15 int getint(){
16     int v=0,sign=1; char ch=getchar();
17     while(!isdigit(ch)) {if(ch==‘-‘) sign=-1; ch=getchar();}
18     while(isdigit(ch))  {v=v*10+ch-‘0‘; ch=getchar();}
19     return v*sign;
20 }
21 const int N=200010,INF=~0u>>2;
22 const double eps=1e-8;
23 /*******************template********************/
24
25 int t[N<<2],n,m;
26 void update(int p,int v){
27     for(t[p+=n]=v,p>>=1;p;p>>=1)
28         t[p]=max(t[p+p],t[p+p^1]);
29 }
30 int ans;
31 void query(int l,int r){
32     for(l=l+n-1,r=r+n+1;l^r^1;l>>=1,r>>=1){
33         if (!(l&1)) ans=max(t[l^1],ans);
34         if ( r&1) ans=max(t[r^1],ans);
35     }
36 }
37 int main(){
38 #ifndef ONLINE_JUDGE
39     freopen("input.txt","r",stdin);
40 //    freopen("output.txt","w",stdout);
41 #endif
42     while(scanf("%d%d",&n,&m)!=EOF){
43         CC(t,0);
44         F(i,1,n) t[i+n]=getint();
45         D(i,n-1,1) t[i]=max(t[2*i],t[2*i+1]);//这句就是build建树……
46         char s[4];
47         int x,y;
48         F(i,1,m){
49             scanf("%s",s); x=getint(); y=getint();
50             if (s[0]==‘Q‘) {ans=0; query(x,y); printf("%d\n",ans);}
51             if (s[0]==‘U‘) update(x,y);
52         }
53     }
54     return 0;
55 }

zkw线段树(218MS 4296K)

时间: 2024-10-15 07:20:31

【HDOJ】【1754】I Hate It的相关文章

【HDOJ图论题集】【转】

1 =============================以下是最小生成树+并查集====================================== 2 [HDU] 3 1213 How Many Tables 基础并查集★ 4 1272 小希的迷宫 基础并查集★ 5 1325&&poj1308 Is It A Tree? 基础并查集★ 6 1856 More is better 基础并查集★ 7 1102 Constructing Roads 基础最小生成树★ 8 1232

【HDOJ】1754 I Hate It

线段树. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 #define mymax(a, b) (a>b) ? a:b 7 8 const int maxn = 200005; 9 10 int nums[maxn<<2]; 11 12 void PushUP(int rt) { 13 nums[rt] = mymax(

【HDOJ】4956 Poor Hanamichi

基本数学题一道,看错位数,当成大数减做了,而且还把方向看反了.所求为最接近l的值. 1 #include <cstdio> 2 3 int f(__int64 x) { 4 int i, sum; 5 6 i = sum = 0; 7 while (x) { 8 if (i & 1) 9 sum -= x%10; 10 else 11 sum += x%10; 12 ++i; 13 x/=10; 14 } 15 return sum; 16 } 17 18 int main() { 1

【HDOJ】1099 Lottery

题意超难懂,实则一道概率论的题目.求P(n).P(n) = n*(1+1/2+1/3+1/4+...+1/n).结果如果可以除尽则表示为整数,否则表示为假分数. 1 #include <cstdio> 2 #include <cstring> 3 4 #define MAXN 25 5 6 __int64 buf[MAXN]; 7 8 __int64 gcd(__int64 a, __int64 b) { 9 if (b == 0) return a; 10 else return

【HDOJ】2844 Coins

完全背包. 1 #include <stdio.h> 2 #include <string.h> 3 4 int a[105], c[105]; 5 int n, m; 6 int dp[100005]; 7 8 int mymax(int a, int b) { 9 return a>b ? a:b; 10 } 11 12 void CompletePack(int c) { 13 int i; 14 15 for (i=c; i<=m; ++i) 16 dp[i]

【HDOJ】3509 Buge&#39;s Fibonacci Number Problem

快速矩阵幂,系数矩阵由多个二项分布组成.第1列是(0,(a+b)^k)第2列是(0,(a+b)^(k-1),0)第3列是(0,(a+b)^(k-2),0,0)以此类推. 1 /* 3509 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #incl

【HDOJ 4763】 Theme Section (KMP+strstr)

[HDOJ 4763] Theme Section Theme Section Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1999    Accepted Submission(s): 947 Problem Description It's time for music! A lot of popular musicians a

【HDOJ 4768】 Flyer (等差数列+二分)

[HDOJ 4768] Flyer (等差数列+二分) Flyer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2022    Accepted Submission(s): 743 Problem Description The new semester begins! Different kinds of student soc

【HDOJ 5379】 Mahjong tree

[HDOJ 5379] Mahjong tree 往一颗树上标号 要求同一父亲节点的节点们标号连续 同一子树的节点们标号连续 问一共有几种标法 画了一画 发现标号有二叉树的感觉 初始标号1~n 根结点1可以标1或n 否则其他情况无法让下面的子树满足各自连续并且该根的儿子节点都要连续 根结点下的节点平分其他标号 画一画可以发现 每个根下最多有两颗子树 否则无法满足条件 并且两颗子树占据剩余标号的左右两边 中间夹的必须是叶子 这样才能满足该根下的儿子节点标号连续 若根下只有一颗子树 同样可以选择占剩

【HDOJ】1818 It&#39;s not a Bug, It&#39;s a Feature!

状态压缩+优先级bfs. 1 /* 1818 */ 2 #include <iostream> 3 #include <queue> 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <algorithm> 8 using namespace std; 9 10 #define MAXM 105 11 12 typedef struct {