洛谷 P816 忠诚 题解

每日一题 day28 打卡

Analysis

这道题用线段树维护区间最小值很简单,因为没有修改所以连lazy_tag都不用,但是这道题可以用树状数组维护区间最小值,非常骚气。

线段树代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define int long long
 7 #define maxn 1000000+10
 8 using namespace std;
 9 inline int read() 
10 {
11     int x=0;
12     bool f=1;
13     char c=getchar();
14     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
15     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
16     if(f) return x;
17     return 0-x;
18 }
19 inline void write(int x)
20 {
21     if(x<0){putchar('-');x=-x;}
22     if(x>9)write(x/10);
23     putchar(x%10+'0');
24 }
25 int m,n;
26 int a[maxn];
27 struct Segment_tree
28 {
29     struct Segment_tree_node
30     {
31         int l,r,val;
32     }node[maxn*4];
33     int n;
34     inline int size() {return n;} 
35     inline int left_s(int x) {return (x<<1);}
36     inline int right_s(int x) {return ((x<<1)|1);}
37     inline void init(int l,int r)
38     {
39         n=r-l+1;
40         node[1].l=1;
41         node[1].r=n;
42         build(1);
43     }
44     inline void push_up(int x)
45     {
46         node[x].val=min(node[left_s(x)].val,node[right_s(x)].val);
47     }
48     inline void build(int x)
49     {
50         if(node[x].l==node[x].r)
51         {
52             node[x].val=a[node[x].l];
53             return;
54         }
55         int mid=(node[x].l+node[x].r)>>1;
56         node[left_s(x)].l=node[x].l;
57         node[left_s(x)].r=mid;
58         build(left_s(x));
59         node[right_s(x)].l=mid+1;
60         node[right_s(x)].r=node[x].r;
61         build(right_s(x));
62         push_up(x);
63     }
64     inline int query(int x,int l,int r)
65     {
66         if(node[x].l==l&&node[x].r==r)
67         {
68             return node[x].val;
69         }
70         int mid=(node[x].l+node[x].r)>>1;
71         if(r<=mid) return query(left_s(x),l,r);
72         if(l>mid) return query(right_s(x),l,r);
73         return min(query(left_s(x),l,mid),query(right_s(x),mid+1,r));
74     }
75 }t;
76 signed main()
77 {
78     m=read();n=read();
79     for(int i=1;i<=m;i++) a[i]=read();
80     t.init(1,m);
81     for(int i=1;i<=n;i++)
82     {
83         int x=read(),y=read();
84         int ans=t.query(1,x,y);
85         write(ans);
86         printf(" ");
87     }
88     return 0;
89 }

树状数组代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define int long long
 7 #define maxn 1000000+10
 8 #define INF 2147483647
 9 using namespace std;
10 inline int read() 
11 {
12     int x=0;
13     bool f=1;
14     char c=getchar();
15     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
16     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
17     if(f) return x;
18     return 0-x;
19 }
20 inline void write(int x)
21 {
22     if(x<0){putchar('-');x=-x;}
23     if(x>9)write(x/10);
24     putchar(x%10+'0');
25 }
26 int m,n;
27 int a[maxn];
28 int tree[maxn];
29 inline int lowbit(int num)
30 {
31     return num&(-num);
32 }
33 inline void update(int s,int num)
34 {
35     int i=s;
36     while(i<=m)
37     {
38         if(tree[i]>num)
39             tree[i]=num;
40         else return; 
41         i+=lowbit(i);
42     }
43 }
44 inline int query(int l,int r)
45 {
46     int res=INF,i=r;
47     while(i>=l)
48     {
49         if(i-lowbit(i)>l)
50         {
51             res=min(res,tree[i]);
52             i-=lowbit(i);
53         }
54         else 
55         {
56             res=min(res,a[i]);
57             --i;
58         }
59     }
60     return res;
61  } 
62 signed main()
63 {
64     memset(tree,127,sizeof(tree));
65     m=read();n=read();
66     for(int i=1;i<=m;i++) 
67     {
68         a[i]=read();
69         update(i,a[i]);
70     }
71     for(int i=1;i<=n;i++)
72     {
73         int x=read(),y=read();
74         int ans=query(x,y);
75         write(ans);
76         printf(" ");
77     }
78     return 0;
79 }

请各位大佬斧正(反正我不认识斧正是什么意思)

原文地址:https://www.cnblogs.com/handsome-zyc/p/11745807.html