zoukankan      html  css  js  c++  java
  • 线段树基础

    题集:http://blog.csdn.net/qq574857122/article/details/11727859

    单点更新:

    HDU 1166 单点改值+区间求和;

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 
     6 #define LL(x) (x<<1)
     7 #define RR(x) (x<<1|1)
     8 #define MID(a,b) (a+((b-a)>>1))
     9 const int N=50005;
    10 
    11 struct node
    12 {
    13     int lft,rht;
    14     int sum;
    15     int mid()
    16     {
    17         return MID(lft,rht);
    18     }
    19 };
    20 
    21 int y[N],n;
    22 
    23 struct Segtree
    24 {
    25     node tree[N*4];
    26     void build(int lft,int rht,int ind)
    27     {
    28         tree[ind].lft=lft;
    29         tree[ind].rht=rht;
    30         tree[ind].sum=0;
    31         if(lft==rht) tree[ind].sum=y[lft];
    32         else
    33         {
    34             int mid=tree[ind].mid();
    35             build(lft,mid,LL(ind));
    36             build(mid+1,rht,RR(ind));
    37             tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
    38         }
    39     }
    40     void updata(int pos,int ind,int valu)
    41     {
    42         if(tree[ind].lft==tree[ind].rht) tree[ind].sum+=valu;
    43         else
    44         {
    45             int mid=tree[ind].mid();
    46             if(pos<=mid) updata(pos,LL(ind),valu);
    47             else updata(pos,RR(ind),valu);
    48             tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
    49         }
    50     }
    51     int query(int st,int ed,int ind)
    52     {
    53         int lft=tree[ind].lft,rht=tree[ind].rht;
    54         if(st<=lft&&rht<=ed) return tree[ind].sum;
    55         else
    56         {
    57             int mid=tree[ind].mid();
    58             int sum1=0,sum2=0;
    59             if(st<=mid) sum1=query(st,ed,LL(ind));
    60             if(ed>mid) sum2=query(st,ed,RR(ind));
    61             return sum1+sum2;
    62         }
    63     }
    64 } seg;
    65 int main()
    66 {
    67     int t,t_cnt=0;
    68     scanf("%d",&t);
    69     while(t--)
    70     {
    71         int a,b;
    72         char str[10];
    73         scanf("%d",&n);
    74         for(int i=1; i<=n; i++) scanf("%d",&y[i]);
    75         seg.build(1,n,1);
    76 
    77         printf("Case %d:
    ",++t_cnt);
    78         while(1)
    79         {
    80             scanf("%s",str);
    81             if(strcmp(str,"End")==0) break;
    82             scanf("%d%d",&a,&b);
    83             if(strcmp(str,"Add")==0) seg.updata(a,1,b);
    84             else if(strcmp(str,"Sub")==0) seg.updata(a,1,-b);
    85             else printf("%d
    ",seg.query(a,b,1));
    86         }
    87     }
    88     return 0;
    89 }
    View Code

    HDU1574 单点改值+区间求最值:

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstdio>
      4 #include <cstdlib>
      5 #include <cstring>
      6 using namespace std;
      7 #define LL(x) (x<<1)
      8 #define RR(x) (x<<1|1)
      9 #define MID(a,b) (a+((b-a)>>1))
     10 const int N=200010;
     11 struct node
     12 {
     13     int lft,rht;
     14     int sum,maxn;
     15     int mid()
     16     {
     17         return MID(lft,rht);
     18     }
     19 };
     20 int y[N],n;
     21 
     22 struct Segtree
     23 {
     24     node tree[N*4];
     25     void build(int lft,int rht,int ind)
     26     {
     27         tree[ind].lft=lft;
     28         tree[ind].rht=rht;
     29         tree[ind].sum = 0;
     30         tree[ind].maxn = 0;
     31         if(lft == rht) tree[ind].sum=y[lft],tree[ind].maxn = y[lft];
     32         else
     33         {
     34             int mid=tree[ind].mid();
     35             build(lft,mid,LL(ind));
     36             build(mid+1,rht,RR(ind));
     37             tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
     38             tree[ind].maxn=max(tree[ind].maxn,max(tree[LL(ind)].maxn,tree[RR(ind)].maxn));
     39         }
     40     }
     41     void updata(int pos,int ind,int valu)
     42     {
     43         if(tree[ind].lft==tree[ind].rht)
     44         {
     45             tree[ind].maxn = valu;///直接改值
     46             ///tree[ind].maxn += valu;///加上某值
     47         }
     48 
     49         else
     50         {
     51             int mid=tree[ind].mid();
     52             if(pos <= mid) updata(pos,LL(ind),valu);
     53             else updata(pos,RR(ind),valu);
     54             tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
     55             tree[ind].maxn=max(tree[ind].maxn,max(tree[LL(ind)].maxn,tree[RR(ind)].maxn));
     56         }
     57     }
     58     int query(int st,int ed,int ind)
     59     {
     60         int lft = tree[ind].lft,rht=tree[ind].rht;
     61         if(st<=lft&&rht<=ed)
     62         {
     63             return tree[ind].maxn;
     64             ///return tree[ind].sum;///就是区间求和
     65         }
     66         else
     67         {
     68             int mid=tree[ind].mid();
     69             int sum1=0,sum2=0;
     70             if(st <= mid)
     71                 sum1=max(sum1,query(st,ed,LL(ind)));
     72             if(ed > mid)
     73                 sum2=max(sum2,query(st,ed,RR(ind)));
     74             return max(sum1,sum2);
     75             ///返回区间和
     76 ///            if(st<=mid) sum1=query(st,ed,LL(ind));
     77 ///            if(ed>mid) sum2=query(st,ed,RR(ind));
     78 ///            return sum1+sum2;
     79         }
     80     }
     81 } seg;
     82 int main()
     83 {
     84     int t,t_cnt=0,m;
     85     while(~scanf("%d%d",&n,&m))
     86     {
     87         int a,b;
     88         char str[10];
     89         for(int i=1; i<=n; i++)
     90             scanf("%d",&y[i]);
     91         seg.build(1,n,1);
     92         while(m--)
     93         {
     94             scanf("%s",str);
     95             scanf("%d%d",&a,&b);
     96             if(strcmp(str,"U")==0)///单点改值
     97                 seg.updata(a,1,b);
     98             else
     99                 printf("%d
    ",seg.query(a,b,1));///求最大值
    100         }
    101     }
    102     return 0;
    103 }
    修改上面的模板即可

    HDU 1394 给一个序列,依次把最后一个数移到第一个数的位置上,求n个序列最小逆序数。

    求初始逆序对数nlogn , 其他逆序对数O(1),也可以用树状数组,对数列的要求不高,不必非得连续也能求(离散化)

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define clr(a, x) memset(a, x, sizeof a)
     6 #define repu(i, a, b) for(int i = a; i < b; i++)
     7 #define ls (rt<<1)
     8 #define rs (ls|1)
     9 #define lson l, mid, ls
    10 #define rson mid+1, r, rs
    11 #define INF 0x3f3f3f3f
    12 using namespace std;
    13 const int maxn=100050;
    14 struct SegmentTree
    15 {
    16     int sum[maxn<<2];
    17     void pushup(int rt)
    18     {
    19         sum[rt]=sum[ls]+sum[rs];
    20     }
    21     void build(int l,int r,int rt)
    22     {
    23         sum[rt]= 0;
    24         if(l == r)
    25             return ;
    26         int mid = (l+r)>>1;
    27         build(lson);
    28         build(rson);
    29     }
    30     void update(int p, int l, int r, int rt)
    31     {
    32         if(l==r)
    33         {
    34             cout<<rt<<endl;
    35             sum[rt]++;///逆序数
    36             ///sum[rt] += add;///区间求和,add是参数传进来
    37             ///Max[rt] = add;///区间最值
    38             return ;
    39         }
    40         int mid=l+r>>1;
    41         if(p <= mid) update(p, lson);
    42         if(p > mid) update(p, rson);
    43         pushup(rt);
    44     }
    45     int query(int L, int R, int l, int r, int rt)
    46     {
    47         if(L <= l && R >= r)
    48             return sum[rt];
    49         int mid = l + r >> 1;
    50         int ans=0;
    51         if(L <= mid)
    52             ans += query(L, R, lson);
    53         if(R > mid)
    54             ans += query(L, R, rson);
    55         return ans;
    56     }
    57 } st;
    58 int main()
    59 {
    60     int n, m, a[maxn];
    61     while(~scanf("%d", &n))
    62     {
    63         st.build(0,n-1,1);
    64         int tot = 0;
    65         repu(i,0,n)
    66         {
    67             scanf("%d",&a[i]);
    68             tot += st.query(a[i],n-1,0,n-1,1);///a[i]做左区间
    69             st.update(a[i],0,n-1,1);///在a[i]这个位置上更新sum
    70         }
    71         ///tot就是初始序列的逆序对数
    72         int minn = INF;
    73         ///1 3 6 9 0 8 5 7 4 2
    74         ///2 1 3 6 9 0 8 5 7 4
    75         ///2后面每一个比2大的数字都应该-1
    76         ///2在第一个位置上,后面肯定有0,1是逆序对
    77         ///因此公式就是tot - (n - 2 - 1) + 2;
    78         for(int i = n-1; i>0; i--)///倒着来,才能用下面的公式
    79         {
    80             tot = tot - (n - a[i] - 1) + a[i];
    81             minn = min(minn,tot);
    82         }
    83         printf("%d
    ",minn);
    84     }
    85     return 0;
    86 }
    求初始逆序数用到线段树,只解决排序后是连续的数列

    HDU 2759(维护区间最大位置信息)

    题目大意:有一块h*w的矩形广告板,要往上面贴广告,然后给n个1*wi的广告,要求把广告贴上去,而且要求广告要尽量往上贴并且尽量靠左,求第n个广告的所在的位置,不能贴则为-1;

    hh代码--还没理解透

    区间更新

    HDU 1698:区间[a,b]里的数更新为c,问最后这N个数的和是多少;

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 using namespace std;
      5 #define LL(x) (x<<1)
      6 #define RR(x) (x<<1|1)
      7 #define MID(a,b) (a+((b-a)>>1))
      8 const int N=100005;
      9 struct node
     10 {
     11     int left,right;
     12     int sum,type;
     13     int mid()
     14     {
     15         return MID(left,right);
     16     }
     17     void fun(int tmp)///这个函数是干嘛的。。。
     18     {
     19         type = tmp;
     20         sum =(right-left+1)*type;
     21     }
     22 ///    void fun(int tmp)///对区间内的数做加操作
     23 ///    {
     24 ///        type += tmp;
     25 ///        sum  +=(right-left+1)*type;
     26 ///    }
     27 };
     28 struct Segtree
     29 {
     30     node tree[N*4];
     31     void build(int left,int right,int ind)
     32     {
     33         tree[ind].left=left;
     34         tree[ind].right=right;
     35         tree[ind].sum=right-left+1;
     36         tree[ind].type=1;
     37         if(left!=right)
     38         {
     39             int mid=tree[ind].mid();
     40             build(left,mid,LL(ind));
     41             build(mid+1,right,RR(ind));
     42         }
     43     }
     44     void relax(int ind)
     45     {
     46         if(tree[ind].type)
     47         {
     48             tree[LL(ind)].fun(tree[ind].type);
     49             tree[RR(ind)].fun(tree[ind].type);
     50             tree[ind].type=0;
     51         }
     52     }
     53     void updata(int st,int ed,int ind,int type)///区间更新
     54     {
     55         int left=tree[ind].left,right=tree[ind].right;
     56         if(st<=left&&right<=ed)
     57             tree[ind].fun(type);
     58         else
     59         {
     60             relax(ind);
     61             int mid = tree[ind].mid();
     62             if(st<=mid)
     63                 updata(st,ed,LL(ind),type);
     64             if(ed>mid)
     65                 updata(st,ed,RR(ind),type);
     66             tree[ind].sum = tree[LL(ind)].sum + tree[RR(ind)].sum;
     67         }
     68     }
     69     int query(int st,int ed,int ind)///区间求和
     70     {
     71         int left=tree[ind].left,right=tree[ind].right;
     72         if(st<=left&&right<=ed) return tree[ind].sum;
     73         else
     74         {
     75             relax(ind);
     76             int mid=tree[ind].mid();
     77             int sum1=0,sum2=0;
     78             if(st<=mid) sum1=query(st,ed,LL(ind));
     79             if(ed> mid) sum2=query(st,ed,RR(ind));
     80             return sum1+sum2;
     81         }
     82     }
     83 } seg;
     84 int main()
     85 {
     86     int t,t_cnt=0;
     87     scanf("%d",&t);
     88     while(t--)
     89     {
     90         int n,m,a,b,c;
     91         scanf("%d%d",&n,&m);
     92         seg.build(1,n,1);
     93         while(m--)
     94         {
     95             scanf("%d%d%d",&a,&b,&c);
     96             seg.updata(a,b,1,c);
     97         }
     98         printf("Case %d: The total value of the hook is %d.
    ",++t_cnt,seg.query(1,n,1));
     99     }
    100     return 0;
    101 }
    View Code

    还有今天做的题,偏偏找了一个错的模板,改了2个小时。。。真是愚蠢

    HDU5023:区间改值,查询区间内不同的具体数字(并不是个数),比如1 2 3 3 2 区间1~5内查询答案是1 2 3

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<set>
      4 #include<algorithm>
      5 using namespace std;
      6 #define lson l, mid, root<<1
      7 #define rson mid+1, r, root<<1|1
      8 const int N = 1e6 + 5;
      9 set <int> s;
     10 set <int> ::iterator it;
     11 struct Node
     12 {
     13     int color;
     14     int left;
     15     int right;
     16     int mid;
     17 } a[N<<2];
     18 
     19 void Push_Down(int root)
     20 {
     21     if(a[root].color)
     22     {
     23         a[root<<1].color = a[root].color;
     24         a[root<<1|1].color = a[root].color;
     25         a[root].color = 0;
     26     }
     27 }
     28 void Build_Tree(int l, int r, int root)
     29 {
     30     int mid = (l + r) >> 1;
     31     a[root].left = l;
     32     a[root].right = r;
     33     a[root].mid = mid;
     34     a[root].color = 2;
     35     if(l == r) return;
     36     Build_Tree(lson);
     37     Build_Tree(rson);
     38 }
     39 void Update(int l, int r, int c, int root)
     40 {
     41     if(a[root].left == l && a[root].right == r)
     42     {
     43         a[root].color = c;
     44         return;
     45     }
     46     if(a[root].color == c) return;
     47     Push_Down(root);
     48     if(l > a[root].mid) Update(l, r, c, root<<1|1);
     49     else if(r <= a[root].mid) Update(l, r, c, root<<1);
     50     else
     51     {
     52         Update(l, a[root].mid, c, root<<1);
     53         Update(a[root].mid+1, r, c, root<<1|1);
     54     }
     55 }
     56 void Query(int l, int r, int root)
     57 {
     58     if(a[root].color)
     59     {
     60         s.insert(a[root].color);
     61         return ;
     62     }
     63     if(l > a[root].mid) Query(l, r, root<<1|1);
     64     else if(r <= a[root].mid) Query(l, r, root<<1);
     65     else
     66     {
     67         Query(l, a[root].mid, root<<1);
     68         Query(a[root].mid+1, r, root<<1|1);
     69     }
     70 }
     71 int main()
     72 {
     73     int n, m;
     74     int l, r, c;
     75     char op[10];
     76     while(~scanf("%d%d", &n, &m) && (n + m))
     77     {
     78         Build_Tree(1, n, 1);
     79         for(int i = 0; i < m; i++)
     80         {
     81             scanf("%s%d%d", op, &l, &r);
     82             if(op[0] == 'P')
     83             {
     84                 scanf("%d", &c);
     85                 Update(l, r, c, 1);
     86             }
     87             else
     88             {
     89                 s.clear();
     90                 Query(l, r, 1);
     91                 int ss = s.size();
     92                 for(it = s.begin(); it != s.end(); it++)
     93                 {
     94                     printf("%d", *it);
     95                     if(ss > 1) printf(" ");
     96                     ss--;
     97                 }
     98                 printf("
    ");
     99             }
    100         }
    101     }
    102     return 0;
    103 }
    View Code

    POJ3468:区间修改,区间里的数加上c,区间求和;代码和上题中的build和fun函数不同。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<set>
      4 #include<algorithm>
      5 using namespace std;
      6 #define lson l, mid, root<<1
      7 #define rson mid+1, r, root<<1|1
      8 const int N = 1e6 + 5;
      9 set <int> s;
     10 set <int> ::iterator it;
     11 struct Node
     12 {
     13     int color;
     14     int left;
     15     int right;
     16     int mid;
     17 } a[N<<2];
     18 
     19 void Push_Down(int root)
     20 {
     21     if(a[root].color)
     22     {
     23         a[root<<1].color = a[root].color;
     24         a[root<<1|1].color = a[root].color;
     25         a[root].color = 0;
     26     }
     27 }
     28 void Build_Tree(int l, int r, int root)
     29 {
     30     int mid = (l + r) >> 1;
     31     a[root].left = l;
     32     a[root].right = r;
     33     a[root].mid = mid;
     34     a[root].color = 2;
     35     if(l == r) return;
     36     Build_Tree(lson);
     37     Build_Tree(rson);
     38 }
     39 void Update(int l, int r, int c, int root)
     40 {
     41     if(a[root].left == l && a[root].right == r)
     42     {
     43         a[root].color = c;
     44         return;
     45     }
     46     if(a[root].color == c) return;
     47     Push_Down(root);
     48     if(l > a[root].mid) Update(l, r, c, root<<1|1);
     49     else if(r <= a[root].mid) Update(l, r, c, root<<1);
     50     else
     51     {
     52         Update(l, a[root].mid, c, root<<1);
     53         Update(a[root].mid+1, r, c, root<<1|1);
     54     }
     55 }
     56 void Query(int l, int r, int root)
     57 {
     58     if(a[root].color)
     59     {
     60         s.insert(a[root].color);
     61         return ;
     62     }
     63     if(l > a[root].mid) Query(l, r, root<<1|1);
     64     else if(r <= a[root].mid) Query(l, r, root<<1);
     65     else
     66     {
     67         Query(l, a[root].mid, root<<1);
     68         Query(a[root].mid+1, r, root<<1|1);
     69     }
     70 }
     71 int main()
     72 {
     73     int n, m;
     74     int l, r, c;
     75     char op[10];
     76     while(~scanf("%d%d", &n, &m) && (n + m))
     77     {
     78         Build_Tree(1, n, 1);
     79         for(int i = 0; i < m; i++)
     80         {
     81             scanf("%s%d%d", op, &l, &r);
     82             if(op[0] == 'P')
     83             {
     84                 scanf("%d", &c);
     85                 Update(l, r, c, 1);
     86             }
     87             else
     88             {
     89                 s.clear();
     90                 Query(l, r, 1);
     91                 int ss = s.size();
     92                 for(it = s.begin(); it != s.end(); it++)
     93                 {
     94                     printf("%d", *it);
     95                     if(ss > 1) printf(" ");
     96                     ss--;
     97                 }
     98                 printf("
    ");
     99             }
    100         }
    101     }
    102     return 0;
    103 }
    用上两题的模板为什么改不出来呢,摘自另一位大神

     

  • 相关阅读:
    CodeSmith注册错误的解决方法
    我是“坚守者”还是"背叛者"?
    拿什么留住你,我的程序员
    去除HTML代码得函数
    页面之间传递参数得几种方法
    nhibernate source code analyzed (abstract classes in nhibernate2.0)
    Web 2.0时代RSS的.Net实现
    Visual Studio.net 2003安装提示重启问题
    开放思路,综合考虑,心胸开阔,做一个合格的项目经理
    了解实际开发中 Hashtable 的特性原理 .NET, JAVA, PHP
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4731247.html
Copyright © 2011-2022 走看看