zoukankan      html  css  js  c++  java
  • 线段树习题集

    1、洛谷 P3372 【模板】线段树 1

    维护区间和

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ls(p) (p<<1)
     4 #define rs(p) (p<<1|1)
     5 #define ll long long
     6 const int MAXN=1e5+5;
     7 struct node
     8 {
     9     ll sum,lazy;
    10     node(){sum=0,lazy=0;}
    11 }T[MAXN*4];
    12 int a[MAXN];
    13 int n,m;
    14 inline void push_up(int p)
    15 {
    16     T[p].sum=T[ls(p)].sum+T[rs(p)].sum;
    17 }
    18 inline void build(int p,int l,int r)
    19 {
    20     if(l==r) 
    21     {
    22         T[p].sum=a[l];
    23         return;
    24     }
    25     int mid=(l+r)>>1;
    26     build(ls(p),l,mid);
    27     build(rs(p),mid+1,r);
    28     push_up(p);
    29 }
    30 inline void push_down(int p,int l,int r)
    31 {
    32     if(!T[p].lazy) return;
    33     int mid=(l+r)>>1;
    34     T[ls(p)].lazy+=T[p].lazy,T[rs(p)].lazy+=T[p].lazy;
    35     T[ls(p)].sum+=T[p].lazy*(mid-l+1),
    36     T[rs(p)].sum+=T[p].lazy*(r-mid);
    37     T[p].lazy=0;
    38 }
    39 inline void update(int p,int l,int r,int nl,int nr,int k) 
    40 {
    41     if(nl<=l&&nr>=r)
    42     {
    43         T[p].sum+=k*(r-l+1);
    44         T[p].lazy+=k;
    45         return;
    46     }
    47     push_down(p,l,r);
    48     int mid=(l+r)>>1;
    49     if(nl<=mid) update(ls(p),l,mid,nl,nr,k);
    50     if(nr>=mid+1) update(rs(p),mid+1,r,nl,nr,k);
    51     push_up(p);
    52 }
    53 ll query(int p,int l,int r,int nl,int nr)
    54 {
    55     ll ans=0;
    56     if(nl<=l&&nr>=r) return T[p].sum;
    57     push_down(p,l,r);
    58     int mid=(l+r)>>1;
    59     if(nl<=mid) ans+=query(ls(p),l,mid,nl,nr);
    60     if(nr>=mid+1) ans+=query(rs(p),mid+1,r,nl,nr);
    61     return ans;
    62 }
    63 int read()
    64 {
    65     int s=1,x=0;char ch=getchar();
    66     while(!isdigit(ch)){if(ch=='-') s=-1;ch=getchar();}
    67     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
    68     return s*x;
    69 }
    70 int main()
    71 {
    72     //freopen("testdata.in","r",stdin);
    73     n=read();m=read();
    74     for(int i=1;i<=n;++i) a[i]=read();
    75     build(1,1,n);
    76     int opt,x,y,k;
    77     for(int i=1;i<=m;++i)
    78     {
    79         opt=read();
    80         if(opt==1)//update
    81         {
    82             x=read(),y=read(),k=read();
    83             update(1,1,n,x,y,k);
    84         }
    85         else //query
    86         {
    87             x=read(),y=read();
    88             cout<<query(1,1,n,x,y)<<endl;
    89         }
    90     }
    91     return 0;
    92 }
    View Code

     2、洛谷 P3373 【模板】线段树 2

    乘法优先,乘法分配律

    维护区间和、区间乘积

      1 #include<iostream>
      2 #include<sstream>
      3 #include<fstream>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<iomanip>
      7 #include<cstdlib>
      8 #include<cctype>
      9 #include<vector>
     10 #include<string>
     11 #include<cmath>
     12 #include<ctime>
     13 #include<stack>
     14 #include<queue>
     15 #include<map>
     16 #include<set>
     17 #define mem(a,b) memset(a,b,sizeof(a))
     18 #define random(a,b) (rand()%(b-a+1)+a)
     19 #define ll long long
     20 #define ull unsigned long long
     21 #define e 2.71828182
     22 #define Pi acos(-1.0)
     23 #define ls(n) (n<<1)
     24 #define rs(n) (n<<1|1)
     25 using namespace std;
     26 const int MAXN=1e5+5;
     27 int N,M,P;
     28 int read()
     29 {
     30     int s=1,x=0;
     31     char ch=getchar();
     32     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
     33     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
     34     return x*s;
     35 }
     36 struct node
     37 {
     38     ll sum,tagc,tagj;
     39     node(){sum=0,tagc=1,tagj=0;}
     40 }T[MAXN*4];
     41 int a[MAXN];
     42 inline void push_up(int p)
     43 {
     44     T[p].sum=(T[ls(p)].sum+T[rs(p)].sum)%P;
     45 }
     46 inline void build(int p,int l,int r)
     47 {
     48     if(l==r) 
     49     {
     50         T[p].sum=a[l];
     51         return ;
     52     }
     53     int mid=(l+r)>>1;
     54     build(ls(p),l,mid);
     55     build(rs(p),mid+1,r);
     56     push_up(p);
     57 }
     58 inline void push_down(int p,int l,int r)
     59 {
     60     if(T[p].tagc==1&&T[p].tagj==0) return;
     61     T[ls(p)].tagc=(T[ls(p)].tagc*T[p].tagc)%P,T[rs(p)].tagc=(T[rs(p)].tagc*T[p].tagc)%P;
     62     T[ls(p)].tagj=(T[ls(p)].tagj*T[p].tagc)%P,T[rs(p)].tagj=(T[rs(p)].tagj*T[p].tagc)%P;
     63     T[ls(p)].sum=(T[ls(p)].sum*T[p].tagc)%P,T[rs(p)].sum=(T[rs(p)].sum*T[p].tagc)%P;
     64     T[p].tagc=1;
     65     int mid=(l+r)>>1;
     66     T[ls(p)].tagj=(T[ls(p)].tagj+T[p].tagj)%P,T[rs(p)].tagj=(T[rs(p)].tagj+T[p].tagj)%P;
     67     T[ls(p)].sum=(T[ls(p)].sum+(mid-l+1)*T[p].tagj)%P,T[rs(p)].sum=(T[rs(p)].sum+(r-mid)*T[p].tagj)%P;
     68     T[p].tagj=0;
     69 }
     70 inline void update_c(int p,int l,int r,int nl,int nr,int k)
     71 {
     72     if(nl<=l&&nr>=r)
     73     {
     74         T[p].sum=(T[p].sum*k)%P;
     75         T[p].tagc=(T[p].tagc*k)%P;
     76         T[p].tagj=(T[p].tagj*k)%P;
     77         return;
     78     }
     79     int mid=(l+r)>>1;
     80     push_down(p,l,r);
     81     if(nl<=mid) update_c(ls(p),l,mid,nl,nr,k);
     82     if(nr>=mid+1) update_c(rs(p),mid+1,r,nl,nr,k);
     83     push_up(p);
     84 }
     85 inline void update_j(int p,int l,int r,int nl,int nr,int k)
     86 {
     87     if(nl<=l&&nr>=r)
     88     {
     89         T[p].tagj=(T[p].tagj+k)%P;
     90         T[p].sum=(T[p].sum+(r-l+1)*k)%P;
     91         return;
     92     }
     93     int mid=(l+r)>>1;
     94     push_down(p,l,r);
     95     if(nl<=mid) update_j(ls(p),l,mid,nl,nr,k);
     96     if(nr>=mid+1) update_j(rs(p),mid+1,r,nl,nr,k);
     97     push_up(p); 
     98 }
     99 ll query(int p,int l,int r,int nl,int nr)
    100 {
    101     ll ans=0;
    102     if(nl<=l&&nr>=r)    return T[p].sum%P;
    103     int mid=(l+r)>>1;
    104     push_down(p,l,r);
    105     if(nl<=mid) ans=(ans+query(ls(p),l,mid,nl,nr))%P;
    106     if(nr>=mid+1) ans=(ans+query(rs(p),mid+1,r,nl,nr))%P;
    107     return ans;
    108 }
    109 int main()
    110 {
    111     N=read(),M=read(),P=read();
    112     for(int i=1;i<=N;++i) a[i]=read();
    113     build(1,1,N);
    114     int opt,x,y,k;
    115     while(M--)
    116     {
    117         opt=read(),x=read(),y=read();
    118         if(opt==1)
    119         {
    120             k=read();
    121             update_c(1,1,N,x,y,k);
    122         }
    123         else if(opt==2)
    124         {
    125             k=read();
    126             update_j(1,1,N,x,y,k);
    127         }
    128         else 
    129             cout<<query(1,1,N,x,y)<<endl;
    130         //for(int i=1;i<=N;++i)
    131         //cout<<query(1,1,N,i,i)<<' '<<endl;
    132     }
    133 }
    View Code

    3、POJ 2991 Crane

    牵扯到了计算几何,线段树很神奇。题目有多组数据,所以每次建树的时候要记得把懒标记给清零。

    维护向量

      1 #include<iostream>
      2 #include<sstream>
      3 #include<fstream>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<iomanip>
      7 #include<cstdlib>
      8 #include<cctype>
      9 #include<vector>
     10 #include<string>
     11 #include<cmath>
     12 #include<ctime>
     13 #include<stack>
     14 #include<queue>
     15 #include<map>
     16 #include<set>
     17 #define mem(a,b) memset(a,b,sizeof(a))
     18 #define random(a,b) (rand()%(b-a+1)+a)
     19 #define ll long long
     20 #define ull unsigned long long
     21 #define e 2.71828182
     22 #define Pi acos(-1.0)
     23 #define ls(n) (n<<1)
     24 #define rs(n) (n<<1|1)
     25 #define eps 1e-9
     26 using namespace std;
     27 const int MAXN=1e4+10;
     28 struct node
     29 {
     30     double x,y;
     31     int add;//lazy tag
     32     node(){x=0.0,y=0.0,add=0;}
     33 }T[MAXN<<2];
     34 int ang[MAXN];
     35 inline void push_up(int p)
     36 {
     37     T[p].x=T[rs(p)].x+T[ls(p)].x;
     38     T[p].y=T[rs(p)].y+T[ls(p)].y;
     39 }
     40 inline void rotate(int p,int angle)
     41 {
     42     double x=T[p].x,y=T[p].y;
     43     double tmp=Pi/180*angle;
     44     T[p].x=cos(tmp)*x-sin(tmp)*y;
     45     T[p].y=sin(tmp)*x+cos(tmp)*y;
     46 }
     47 inline void push_down(int p,int l,int r)
     48 {
     49     if(!T[p].add) return;
     50     rotate(ls(p),T[p].add),rotate(rs(p),T[p].add);
     51     T[ls(p)].add+=T[p].add,T[rs(p)].add+=T[p].add;
     52     T[p].add=0;
     53 }
     54 inline void build(int p,int l,int r)
     55 {
     56     if(l==r)
     57     {
     58         scanf("%lf",&T[p].y);
     59         T[p].x=0,T[p].add=0;
     60         return;
     61     }
     62     T[p].add=0;//因为有多组数据,所以非叶结点也要清除懒标记 
     63     int mid=(l+r)>>1;
     64     build(ls(p),l,mid);
     65     build(rs(p),mid+1,r);
     66     push_up(p);
     67 }
     68 inline void update(int p,int l,int r,int nl,int nr,int k)
     69 {
     70     if(nl<=l&&nr>=r)
     71     {
     72         T[p].add+=k;
     73         rotate(p,k);
     74         return ;
     75     }
     76     push_down(p,l,r);
     77     int mid=(l+r)>>1;
     78     if(nl<=mid) update(ls(p),l,mid,nl,nr,k);
     79     if(nr>mid) update(rs(p),mid+1,r,nl,nr,k);
     80     push_up(p);
     81 }
     82 int n,c;
     83 int main()
     84 {
     85     int cnt=0;
     86     while(~scanf("%d%d",&n,&c))
     87     {
     88         if(cnt++) puts("");
     89         build(1,1,n);
     90         for(int i=1;i<=n;++i) 
     91             ang[i]=180;
     92         
     93         int s,a;
     94         while(c--)
     95         {
     96             scanf("%d%d",&s,&a);
     97             int x=(a-ang[s]+360)%360;
     98             update(1,1,n,s+1,n,x);
     99             ang[s]=a;
    100             printf("%.2lf %.2lf
    ",T[1].x,T[1].y); 
    101         }
    102     }
    103     return 0;
    104 }
    View Code

    4、CF1199D Welfare State

    单点修改、区间满足条件的修改、单点查询

    维护区间最小值

      1 #include<iostream>
      2 #include<sstream>
      3 #include<fstream>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<iomanip>
      7 #include<cstdlib>
      8 #include<cctype>
      9 #include<vector>
     10 #include<string>
     11 #include<cmath>
     12 #include<ctime>
     13 #include<stack>
     14 #include<queue>
     15 #include<map>
     16 #include<set>
     17 #define mem(a,b) memset(a,b,sizeof(a))
     18 #define random(a,b) (rand()%(b-a+1)+a)
     19 #define ll long long
     20 #define ull unsigned long long
     21 #define e 2.71828182
     22 #define Pi acos(-1.0)
     23 #define ls(rt) (rt<<1)
     24 #define rs(rt) (rt<<1|1)
     25 #define INF 0x7fffffff
     26 using namespace std;
     27 const int MAXN=2e5+5;
     28 int a[MAXN],n,q,p,x;
     29 int read()
     30 {
     31     int s=1,x=0;
     32     char ch=getchar();
     33     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
     34     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
     35     return x*s;
     36 }
     37 struct node
     38 {
     39     int Min,tag;
     40 }T[MAXN<<2];
     41 inline void push_up(int rt)
     42 {
     43     T[rt].Min=min(T[ls(rt)].Min,T[rs(rt)].Min);
     44 }
     45 inline void build(int rt,int l,int r)
     46 {
     47     if(l==r)
     48     {
     49         T[rt].Min=a[l];
     50         T[rt].tag=0;
     51         return ;
     52     }
     53     T[rt].tag=0,T[rt].Min=INF;
     54     int mid=(l+r)>>1;
     55     build(ls(rt),l,mid);
     56     build(rs(rt),mid+1,r);
     57     push_up(rt);
     58 }
     59 inline void push_down(int rt,int l,int r)
     60 {
     61     if(!T[rt].tag) return ;
     62     T[ls(rt)].tag=max(T[ls(rt)].tag,T[rt].tag);
     63     T[rs(rt)].tag=max(T[rs(rt)].tag,T[rt].tag);
     64     T[ls(rt)].Min=max(T[ls(rt)].Min,T[rt].tag);
     65     T[rs(rt)].Min=max(T[rs(rt)].Min,T[rt].tag);
     66     T[rt].tag=0;
     67 }
     68 inline void update_single(int rt,int l,int r,int nl,int nr,int k)
     69 {
     70     //nl==nr 
     71     if(l==r)
     72     {
     73         T[rt].Min=k;
     74         return;
     75     }
     76     push_down(rt,l,r);
     77     int mid=(l+r)>>1;
     78     if(nl<=mid) update_single(ls(rt),l,mid,nl,nr,k);
     79     else update_single(rs(rt),mid+1,r,nl,nr,k);
     80     push_up(rt); 
     81 }
     82 inline void update_interval(int rt,int k)
     83 {
     84     if(k<=T[rt].Min) return;
     85     T[rt].Min=k;
     86     T[rt].tag=max(T[rt].tag,k);
     87 }
     88 int query_single(int rt,int l,int r,int nl,int nr)
     89 {
     90     //nl==nr
     91     if(l==r) return T[rt].Min;
     92     push_down(rt,l,r);
     93     int mid=(l+r)>>1;
     94     if(nl<=mid) return query_single(ls(rt),l,mid,nl,nr);
     95     else return query_single(rs(rt),mid+1,r,nl,nr); 
     96 }
     97 int main()
     98 {
     99     n=read();
    100     for(int i=1;i<=n;++i) a[i]=read();
    101     build(1,1,n);
    102     q=read();
    103     int opt;
    104     while(q--)
    105     {
    106         opt=read();
    107         if(opt==1)
    108         {
    109             p=read(),x=read();
    110             update_single(1,1,n,p,p,x);
    111         }
    112         else 
    113         {
    114             x=read();
    115             update_interval(1,x);
    116         }
    117     } 
    118     for(int i=1;i<=n;++i)
    119     cout<<query_single(1,1,n,i,i)<<' '; 
    120 }
    View Code

    5、洛谷 P4198 楼房重建

    维护特殊的LIS,每个结点的左端点包含在内

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ls(rt) rt<<1
     4 #define rs(rt) rt<<1|1
     5 const int MAXN=1e5+5;
     6 int n,m;
     7 struct node
     8 {
     9     double Max;//区间最大值 
    10     int len;//以区间左端点开头的LIS长 
    11 }T[MAXN<<2];
    12 inline void build(int rt,int l,int r)
    13 {
    14     T[rt].Max=0.0,T[rt].len=0;
    15     if(l==r) return;
    16     int mid=(l+r)>>1;
    17     build(ls(rt),l,mid);
    18     build(rs(rt),mid+1,r);    
    19 }
    20 inline int cal(int rt,int l,int r,double x)
    21 {
    22     if(l==r) return T[rt].Max>x;
    23     int mid=(l+r)>>1;
    24     if(T[ls(rt)].Max<=x) return cal(rs(rt),mid+1,r,x);
    25     else return T[rt].len-T[ls(rt)].len+cal(ls(rt),l,mid,x);
    26 }
    27 inline void push_up(int rt,int l,int r)
    28 {
    29     T[rt].Max=max(T[ls(rt)].Max,T[rs(rt)].Max);
    30     int mid=(l+r)>>1;
    31     T[rt].len=T[ls(rt)].len+cal(rs(rt),mid+1,r,T[ls(rt)].Max);
    32 }
    33 inline void update(int rt,int l,int r,int nl,int nr,double x)
    34 {
    35     if(nl<=l&&nr>=r)
    36     {
    37         T[rt].Max=x;
    38         T[rt].len=1;
    39         return;
    40     }
    41     int mid=(l+r)>>1;
    42     if(nl<=mid) update(ls(rt),l,mid,nl,nr,x);
    43     if(nr>mid) update(rs(rt),mid+1,r,nl,nr,x);
    44     push_up(rt,l,r);
    45 }
    46 int query(int rt,int l,int r,int nl,int nr)
    47 {
    48     if(nl<=l&&nr>=r) return T[rt].len;
    49     int mid=(l+r)>>1;
    50     if(nl<=l) return query(ls(rt),l,mid+1,nl,nr);
    51     else return query(rs(rt),mid+1,r,nl,nr);
    52 }
    53 int main()
    54 {
    55     cin>>n>>m;
    56     int xi,yi;
    57     build(1,1,n);
    58     while(m--)
    59     {
    60         cin>>xi>>yi;
    61         update(1,1,n,xi,xi,double(yi)/double(xi));
    62         cout<<query(1,1,n,1,n)<<endl;//T[1].len
    63     }
    64     return 0;
    65 }
    View Code

    线段树维护LIS貌似做不到呀

     6、HDU2492 Ping pong

    找每一个数的前面比他大的数、小的数,后面比他大的数、小的数。用树状数组也能求。

    注意将最后输出结果的数据类型设为long long

    题目中说数据不重复,但没说是1~n的排列,所以如果要用下面的式子需要离散化:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ls(p) (p<<1)
     4 #define rs(p) (p<<1|1)
     5 const int MAXN=1e5+5;
     6 struct node1
     7 {
     8     int val,pos;
     9     bool operator < (const node1& a)
    10     {
    11         return val<a.val;
    12     }
    13 }a[MAXN];
    14 struct node2
    15 {
    16     int sum;
    17 }T[MAXN<<2];
    18 int t,n,Hash[MAXN];
    19 inline void push_up(int p,int l,int r)
    20 {
    21     T[p].sum=T[ls(p)].sum+T[rs(p)].sum;
    22 }
    23 inline void build(int p,int l,int r)
    24 {
    25     memset(T,0,sizeof(T));
    26 }
    27 inline void update(int p,int l,int r,int lr,int x)//single
    28 {
    29     if(l==r)
    30     {
    31         T[p].sum=x;
    32         return;
    33     }
    34     int mid=(l+r)>>1;
    35     if(lr<=mid) update(ls(p),l,mid,lr,x);
    36     else update(rs(p),mid+1,r,lr,x);
    37     push_up(p,l,r);
    38 }
    39 int query(int p,int l,int r,int nl,int nr)
    40 {
    41     if(nr<nl) return 0;
    42     int ans=0;
    43     if(nl<=l&&nr>=r)    return T[p].sum;
    44     int mid=(l+r)>>1;
    45     if(nl<=mid) ans+=query(ls(p),l,mid,nl,nr);
    46     if(nr>mid) ans+=query(rs(p),mid+1,r,nl,nr);
    47     return ans;
    48 }
    49 int main()
    50 {
    51     scanf("%d",&t);
    52     while(t--)
    53     {
    54         scanf("%d",&n);
    55         build(1,1,n);
    56         for(int i=1;i<=n;++i) scanf("%d",&a[i].val),a[i].pos=i;
    57         sort(a+1,a+n+1);
    58         for(int i=1;i<=n;++i) Hash[a[i].pos]=i;
    59         update(1,1,n,Hash[1],1);
    60         //for(int i=1;i<=n;++i) cout<<Hash[i]<<' ';
    61         int preless=0,pregreat=0,sufless=0,sufgreat=0;
    62         long long ans=0;
    63         for(int i=2;i<=n-1;++i)
    64         {
    65             preless=query(1,1,n,1,Hash[i]-1);
    66             pregreat=i-1-preless;//query(1,1,n,Hash[i]+1,n);
    67             sufless=Hash[i]-1-preless;
    68             sufgreat=n-Hash[i]-pregreat;
    69             ans+=preless*sufgreat+pregreat*sufless;
    70             //cout<<"i: "<<i<<' ';
    71             //cout<<"pl: "<<preless<<" pg: "<<pregreat<<" sl: "<<sufless<<" sg: "<<sufgreat<<endl;
    72             update(1,1,n,Hash[i],1);
    73         }
    74         cout<<ans<<endl;
    75     }
    76 }
    View Code

     

  • 相关阅读:
    Some notes in Stanford CS106A(4)
    Some notes in Stanford CS106A(3)
    Some notes in Stanford CS106A(2)
    Some notes in Stanford CS106A(1)
    将前台页面的数据传到后台的方法(不调用ajax,少量数据)
    12、(扩展)获取省份表,填充于下拉列表框的简易js
    iframe刷新问题
    MVC基础
    DataList
    序列化
  • 原文地址:https://www.cnblogs.com/wangzhebufangqi/p/11278219.html
Copyright © 2011-2022 走看看