线段树习题集

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\n",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

 

 

 

 

转载于:https://www.cnblogs.com/wangzhebufangqi/p/11278219.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值