zoukankan      html  css  js  c++  java
  • 数据结构--线段树

    线段树 好久没做全部忘记了 还得重新学一下了

    线段树--单点更新

    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:
    ",++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
    ",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 }
    View Code

     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
    ",Query(1,l,r));
    75             else  {p=l,date=r;Update_One(1,1,n);}
    76         }
    77     }
    78    return 0;
    79 }
    View Code

    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("
    ");
    86     }
    87     return 0;
    88 }
    View Code

    代码有时间补上

    HDU1394

    HDU2795

    题意:

    思路:

     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
    ",ans[i]);
    64         }
    65     }
    66    return 0;
    67 }
    View Code

    HDU1698

    题意:给一个数组 再给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
    ",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.
    ",++T,Tr[1].val);
    76     }
    77    return 0;
    78 }
    View Code

    POJ2828

    POJ2886

    POJ3468

    题意:给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
    ",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 }
    View Code

    POJ3264

    题意:给你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
    ",maxn[0]-minn[0]);
    62         }
    63     }
    64     return 0;
    65 }
    View Code

     HDU5685

    题意:给你一个字符串 求l,r区间内字符串的哈希值,哈希公式为 H(s)=ilen(s)i=1(Si28) (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 }
    View Code

    线段树+区间离散化(校赛的一个题目)

    POJ2528

    POJ3225

    POJ1436

    POJ2991

    POJ3667

     

  • 相关阅读:
    oracle 12C linux centos7.5 安装 12C
    FizzBuzz
    批量判断能否telnet登录
    统计所有机器的挂载情况
    ffmpeg windows vs library 下载地址
    需求文档测试
    接口测试分析
    chrome网页截图
    不要为了测试写一个新系统
    C# 判断是否为数字
  • 原文地址:https://www.cnblogs.com/max88888888/p/6028880.html
Copyright © 2011-2022 走看看