专题:数据结构之线段树

 模板题AHDU 1754I Hate It
 模板题BPOJ 3468A Simple Problem with Integers
  dfs线段树优化(区间最值)COpenJ_Bailian 2452Sticks Problem
 模板题DPOJ 3264Balanced Lineup
  递增数列的区间众数,离散化去重EPOJ 3368Frequent values
  单点查询,区间最值FHDU 2795Billboard
  区间求GCD和区间求LCM,,唯一分解定理+位压缩,线段树优化GHDU 3071Gcd & Lcm game
 填数+求lis,离线化处理HHDU 3564Another LIS
  思维题目 区间最值,离散化/二分IHDU 2305WorstWeather Ever
  最长上升子序列变体 用线段树优化区间最值,离散化  //这个题目前无法提交评测JZOJ 3349Special Subsequence
 

 贪心 线段树优化 区间最值

KZOJ 2451Minimizing maximizer
 反素数表 约瑟夫环的线段树优化LPOJ 2886Who Gets the Most Candies?
 线段树上的插空位+特殊递推,离线化,二分查找MHDU 4288Coder
 和上题一样NCodeForces 85DSum of Medians
 转化为2维,排序后再降维 区间求和 OPOJ 2481Cows
 不会写....PHDU 3950Parking Log
  动态规划 线段树优化QHDU 4521小明系列问题——小明序列
 模板题 需要标记RHDU 1698Just a Hook
 模板题 需要标记SHDU 1166敌兵布阵
 动态规划  线段树预处理信息 T
HDU 3016 
Man Down
 离线处理回答 区间求和UHDU 3333Turing Tree
 集合模拟 区间修改 区间求和VPOJ 3225Help with Intervals
 ...并不需要线段树WHDU 3297Balancing the Scale
 ...并不需要线段树XHDU 2991Generate random numbers
 矩形交并,实际上,可以用stl中的堆来代替YCodeForces 35EParade
 不会写....ZUVA 12436Rip Van Winkle's Code

点击题号阅读题面

线段树真是博大精深...

---

A

模板题:单点更新,求区间最值

 1 /**********************
 2 *@Name:
 3 *
 4 *@Author: Nervending
 5 *@Describtion:
 6 *@DateTime: 2018-02-11 08:43:44
 7 ***********************/
 8 #include <bits/stdc++.h>
 9 #define show(x) cout<<#x<<"="<<x<<endl
10 using namespace std;
11 const int maxn=1e5+10;
12 const int maxm=1e6+10;
13 const int INF=0x3f3f3f3f;
14 typedef long long ll;
15 typedef unsigned long long ull;
16 int casn,n,m,k;
17 
18 struct node{int l,r,num;}tr[maxm<<1];
19 int num[maxm];
20 void build(int now,int s,int t){
21     tr[now]=(node){s,t,num[s]};
22     if(s==t) return;
23     int mid=(s+t)>>1;
24     build(now<<1,s,mid);
25     build(now<<1|1,mid+1,t);
26     tr[now].num=max(tr[now<<1].num,tr[now<<1|1].num);
27 }
28 int query(int s,int t,int now){
29     int l=tr[now].l,r=tr[now].r;
30     if(s<=l&&r<=t) return tr[now].num;
31     int mid=(l+r)>>1,ans=0;
32     if(s<=mid) ans=query(s,t,now<<1);
33     if(t>mid) ans=max(ans,query(s,t,now<<1|1));
34     return ans;
35 }
36 void update(int pos,int x,int now){
37     int l=tr[now].l,r=tr[now].r;
38     if(l==r) {
39         tr[now].num=x;
40         return;
41     }
42     int mid=(l+r)>>1;
43     if(pos<=mid) update(pos,x,now<<1);
44     else update(pos,x,now<<1|1);
45     tr[now].num=max(tr[now<<1].num,tr[now<<1|1].num);
46 }
47 
48 inline int read(){
49     int ret=0,flag=1,ch=getchar();
50     while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
51     while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
52     return flag*ret;
53 }
54 
55 int main(){
56 //#define test
57 #ifdef test
58     freopen("in.txt","r",stdin);
59     freopen("out.txt","w",stdout);
60 #endif
61     while(~scanf("%d%d",&n,&m)){
62         for(int i=1;i<=n;i++){
63             num[i]=read();
64         }
65         build(1,1,n);
66         char ch;
67         while(m--){
68             ch='0';
69             while(ch!='Q'&&ch!='U') ch=getchar();
70             int a=read(),b=read();
71             if(ch=='Q') printf("%d\n",query(a,b,1));
72             else update(a,b,1);
73         }
74     }
75 
76 #ifdef test
77     fclose(stdin);
78     fclose(stdout);
79     system("out.txt");
80 #endif
81     return 0;
82 }
View Code

----

B

模板题:区间更新,求区间和

  1 /**********************
  2 *@Name:
  3 *
  4 *@Author: Nervending
  5 *@Describtion:
  6 *@DateTime: 2018-02-11 22:28:52
  7 ***********************/
  8 #include <cstdio>
  9 #include <string.h>
 10 #include <iostream>
 11 #define show(x) cout<<#x<<"="<<x<<endl
 12 using namespace std;
 13 const int maxn=1e5+10;
 14 const int maxm=5e5+10;
 15 const int INF=0x3f3f3f3f;
 16 typedef long long ll;
 17 typedef unsigned long long ul;
 18 int casn,n,m,k;
 19 struct node{int l,r;long long data,tag;int len(){return r-l+1;}int mid(){return (l+r)>>1;}};
 20 node lst[maxm];
 21 int num[maxm];
 22 inline void clear(int now){
 23     long long &tag=lst[now].tag;
 24     if(tag){
 25         lst[now<<1].tag+=tag;
 26         lst[now<<1|1].tag+=tag;
 27         lst[now<<1].data+=tag*lst[now<<1].len();
 28         lst[now<<1|1].data+=tag*lst[now<<1|1].len();
 29         tag=0;
 30     }
 31 }
 32 void make(int s,int t,int now){
 33     lst[now]=(node){s,t,num[s],0};
 34     if(s==t) return;
 35     int mid=(s+t)>>1;
 36     make(s,mid,now<<1);
 37     make(mid+1,t,now<<1|1);
 38     lst[now].data=lst[now<<1].data+lst[now<<1|1].data;
 39 }
 40 void add(int s,int t,long long x,int now){
 41     node &nd=lst[now];
 42     if(s<=lst[now].l&&t>=lst[now].r){
 43         lst[now].tag+=x;
 44         lst[now].data+=x*lst[now].len();
 45         return;
 46     }
 47     clear(now);
 48     int mid=lst[now].mid();
 49     if(s<=mid) add(s,t,x,now<<1);
 50     if(t>mid)  add(s,t,x,now<<1|1);
 51     lst[now].data=lst[now<<1].data+lst[now<<1|1].data;
 52 }
 53 long long query(int s,int t,int now){
 54     node& nd=lst[now];
 55     if(s<=lst[now].l&&t>=lst[now].r){
 56         return lst[now].data;
 57     }
 58     clear(now);
 59     int mid=lst[now].mid();
 60     long long sum=0;
 61     if(s<=mid) sum+=query(s,t,now<<1);
 62     if(t>mid) sum+=query(s,t,now<<1|1);
 63     return sum;
 64 }
 65 inline int read(){
 66     int num=0,flag=1,ch=getchar();
 67     while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
 68     while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}
 69     return flag*num;
 70 }
 71 
 72 int main(){
 73 //#define test
 74 #ifdef test
 75     freopen("in.txt","r",stdin);
 76     freopen("out.txt","w",stdout);
 77 #endif
 78 
 79     while(~scanf("%d%d",&n,&m)){
 80     for(int i=1;i<=n;i++){
 81             num[i]=read();
 82         }
 83         make(1,n,1);
 84         int a,b,c,ch;
 85         while(m--){
 86             ch=0;
 87             while(ch!='Q'&&ch!='C')ch=getchar();
 88             a=read(),b=read();
 89             if(ch=='Q') {
 90                 printf("%lld\n",query(a,b,1));
 91             }
 92             else {
 93                 c=read();
 94                 add(a,b,c,1);
 95             }
 96         }
 97     }
 98 
 99 #ifdef test
100     fclose(stdin);
101   fclose(stdout);
102     system("out.txt");
103 #endif
104     return 0;
105 }
View Code

 ----

C

dfs,每次分为三段

 1 /**********************
 2 *@Name:
 3 *
 4 *@Author: Nervending
 5 *@Describtion:
 6 *@DateTime: 2018-02-17 17:32:19
 7 ***********************/
 8 #include <bits/stdc++.h>
 9 #define show(x) cout<<#x<<"="<<x<<endl
10 using namespace std;
11 const int maxn=1e5+10;
12 const int maxm=1e6+10;
13 const int INF=0x3f3f3f3f;
14 typedef long long ll;
15 typedef unsigned long long ull;
16 int casn,n,m,k,s[maxn],num[maxn];
17 struct node {int l,r,max;int mid(){return (l+r)>>1;}};
18 node lst[maxm];
19 void make(int s,int t,int now){
20     lst[now]=(node){s,t,0};
21     if(s==t) return;
22     int mid=(s+t)>>1;
23     make(s,mid,now<<1);
24     make(mid+1,t,now<<1|1);
25 }
26 void update(int pos,int x,int now){
27     node &nd=lst[now];
28     if(pos<nd.l||pos>nd.r) return;
29     if(nd.l==nd.r){nd.max=x;return;}
30     update(pos,x,now<<1);update(pos,x,now<<1|1);
31     nd.max=max(lst[now<<1].max,lst[now<<1|1].max);
32 }
33 int query(int s,int t,int now){
34     node& nd=lst[now];
35     if(t<nd.l||s>nd.r) return 0;
36     if(s<=nd.l&&t>=nd.r) return nd.max;
37     return max(query(s,t,now<<1),query(s,t,now<<1|1));
38 }
39 inline int read(){
40     int num=0,flag=1,ch=getchar();
41     while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
42     while(ch>='0'&&ch<='9'){num=(num<<3+num<<1)+ch-'0',ch=getchar();}
43     return flag*num;
44 }
45 
46 int main(){
47 //#define test
48 #ifdef test
49     freopen("in.txt","r",stdin);
50     freopen("out.txt","w",stdout);
51 #endif
52 
53     while(~scanf("%d%d",&n,&m)){
54         for(int i=0;i<n;i++){
55             num[i]=s[i]=read();
56         }
57         sort(num,num+n);
58         k=unique(num,num+n)-num;
59         make(1,k,1);
60         int ans=0;
61         for(int i=0;i<n;i++){
62             int l=lower_bound(num,num+k,s[i]-m)-num;
63             int r=upper_bound(num,num+k,s[i]+m)-num-1;
64             int len=query(l,r,1);
65             ans=max(ans,len+1);
66             update(lower_bound(num,num+k,s[i])-num,len+1,1);
67         }
68         printf("%d\n",ans);
69     }
70 
71 #ifdef test
72     fclose(stdin);
73   fclose(stdout);
74     system("out.txt");
75 #endif
76     return 0;
77 }
View Code

----

D 略

----

E

由于是递增的,只需要线性的去重就行了

去重之后,建立线段树,就行

 1 /**********************
 2   *@Name:
 3 *
 4 *@Author: Nervending
 5 *@Describtion:
 6 *@DateTime: 2018-02-13 12:57:50
 7 ***********************/
 8 #include <cstdio>
 9 #include <algorithm>
10 #define show(x) cout<<#x<<"="<<x<<endl
11 using namespace std;
12 const int maxn=1e5+10;
13 const int maxm=5e5+10;
14 const int INF=0x3f3f3f3f;
15 typedef long long ll;
16 typedef unsigned long long ull;
17 int casn,n,m,k,cnt;
18 int s[maxn],pos[maxn],sum[maxn],num[maxn];
19 struct node{
20     int l,r,mx;
21     int mid(){return (l+r)>>1;}
22 }lst[maxm];
23 void make(int s,int t,int now){
24     lst[now]=(node){s,t,num[s]};
25     if(s==t) return;
26     int mid=(s+t)>>1;
27     make(s,mid,now<<1);
28     make(mid+1,t,now<<1|1);
29     lst[now].mx=max(lst[now<<1].mx,lst[now<<1|1].mx);
30 }
31 int query(int s,int t,int now){
32     node &nd=lst[now];
33     if(s<=nd.l&&t>=nd.r){
34         return nd.mx;
35     }
36     int mid=nd.mid();
37     int ans=0;
38     if(s<=mid) ans=query(s,t,now<<1);
39     if(t>mid)  ans=max(ans,query(s,t,now<<1|1));
40     return ans;
41 }
42 inline int read(){
43     int num=0,flag=1,ch=getchar();
44     while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}
45     while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}
46     return num*flag;
47 }
48 
49 int main(){
50 //#define test
51 #ifdef test
52     freopen("in.txt","r",stdin);
53     freopen("out.txt","w",stdout);
54 #endif
55     while(~scanf("%d",&n)){
56         if(n==0) break;
57         m=read();
58         for(int i=1;i<=n;i++){
59             s[i]=read();
60             num[i]=1;
61             pos[i]=i;
62         }
63         cnt=1;
64         for(int i=2;i<=n;i++){
65             if(s[i]==s[i-1]){
66                 num[cnt]++;
67                 pos[i]=cnt;
68             }else{
69                 pos[i]=++cnt;
70             }
71         }
72         for(int i=1;i<=cnt;i++){
73             sum[i]=sum[i-1]+num[i];
74         }
75         make(1,cnt,1);
76         while(m--){
77             int a=read(),b=read();
78             int l=pos[a],r=pos[b];
79             int ans=0;
80             if(l==r) ans=(b-a+1);
81             else {
82                 ans=max(sum[l]-a+1,b-sum[r-1]);
83                 if(r-l>1){
84                     ans=max(ans,query(l+1,r-1,1));
85                 }
86             }
87             printf("%d\n",ans);
88         }
89     }
90 
91 
92 #ifdef test
93     fclose(stdin);
94   fclose(stdout);
95     system("out.txt");
96 #endif
97     return 0;
98 }
View Code

----

F

可以稍微变形

 1 /**********************
 2 *@Name:
 3 *
 4 *@Author: Nervending
 5 *@Describtion:
 6 *@DateTime: 2018-02-13 21:38:09
 7 ***********************/
 8 #include <bits/stdc++.h>
 9 #define show(x) cout<<#x<<"="<<x<<endl
10 using namespace std;
11 const int maxn=2e5+10;
12 const int maxm=1e6+10;
13 const int INF=0x3f3f3f3f;
14 typedef long long ll;
15 typedef unsigned long long ull;
16 int casn,n,m,k;
17 struct node{
18     int l,r,mx;
19     int mid(){return (l+r)>>1;}
20 }lst[maxm];
21 void make(int s,int t,int now){
22     lst[now]=(node){s,t,m};
23     if(s==t) return;
24     int mid=(s+t)>>1;
25     make(s,mid,now<<1);
26     make(mid+1,t,now<<1|1);
27 }
28 int update(int x,int now){
29     node& nd=lst[now];
30     if(nd.l==nd.r){
31         nd.mx-=x;
32         return nd.l;
33     }
34     int mid=nd.mid(),ret;
35     if(lst[now<<1].mx>=x) ret=update(x,now<<1);
36     else ret=update(x,now<<1|1);
37     nd.mx=max(lst[now<<1].mx,lst[now<<1|1].mx);
38     return ret;
39 }
40 inline int read(){
41     int num=0,flag=1,ch=getchar();
42     while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
43     while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}
44     return flag*num;
45 }
46 
47 int main(){
48 //#define test
49 #ifdef test
50     freopen("in.txt","r",stdin);
51     freopen("out.txt","w",stdout);
52 #endif
53     while(~scanf("%d%d%d",&n,&m,&k)){
54         n=min(n,k);
55         make(1,n,1);
56         while(k--){
57             int len=read();
58             if(len>lst[1].mx)puts("-1");
59             else printf("%d\n",update(len,1));
60         }
61     }
62 
63 
64 #ifdef test
65     fclose(stdin);
66   fclose(stdout);
67     system("out.txt");
68 #endif
69     return 0;
70 }
View Code

----

普通的线段树无法保存一个区间内所有的数字,空间复杂度太高

和GCD,LCM有关的我们就考虑唯一分解定律,gcd就是所有素因子取交集,lcm就是所有素因子取并集

所以实际上我们不需要去保存所有数字的信息,只需要保存所有素因数的个数的交集和并集就行了

但是1-100的素数有25个,需要每个节点一个长度25的数组,而且比较的常数也不低,很可能爆空间

但是同时也发现了只有25个素数,考虑位压缩

我们用0和1表示是否有这个因子,对于可以重复出现的因子,比如:

  2*2*2*2*2*2=64,3*3*3*3=81,5*5=25,7*7=49

我们就多分配几位....但如果是int的话并不能直接堆砌

就拿2,3,5,7来看,分别需要6个,4个,2个,2个,一共12个,还有其他的21个素数呢,int就不够了

所以用longlong就行...

但网上有空间复杂度更好的解法,就是直接用2进制表示个数

那么2最多到6,也就是3位,3是四个也是3位,5和7依然是2位,这就一共是10位

算上其余的21个素数,刚好31位,不会吧爆ing

简单来说,最终的位含义是:

2,2,2,2,3,3,3,3,5,5,7,7,11,13...89,97.一共31位

用2个函数,一个压缩,一个还原.

需要4个辅助常数表,分别是

  素数表prime,用于判定因子

  素数位置表bpos,位操作时快速定位到每个素数所对应的位

  素数幂表,pw 用于还原2,3,5,7的幂

  位操作数 b2-b97,用于位操作的交集和并集

2个区间查询,rmax和rmin rmax取并集,rmin取交集

1个区间修改 update 和更新最值一样,只不过变成了交集和并集

上个最优的代码吧

  1 /**********************
  2 *@Name:
  3 *
  4 *@Author: Nervending
  5 *@Describtion:
  6 *@DateTime: 2018-02-14 01:00:58
  7 ***********************/
  8 #include <bits/stdc++.h>
  9 #define show(x) cout<<#x<<"="<<x<<endl
 10 using namespace std;
 11 const int maxn=1e5+10;
 12 const int maxm=1e6+10;
 13 const int INF=0x3f3f3f3f;
 14 typedef long long ll;
 15 typedef unsigned long long ull;
 16 const int prime[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
 17 const int bpos[25]={28,25,23,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
 18 const int pw[4][10]={{1,2,4,8,16,32,64},{1,3,9,27,81},{1,5,25},{1,7,49}};
 19 const int b2=0x70000000,b3=0x0e000000,b5=0x01800000;
 20 const int b7=0x00600000,b97=0x001fffff;
 21 int casn,n,m,k;
 22 int num[maxn];
 23 int tes[maxn];
 24 inline int read(){
 25     int num=0,flag=1,ch=getchar();
 26     while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}
 27     while(ch>='0'&&ch<='9'){num=(num<<1)+(num<<3)+ch-'0';ch=getchar();}
 28     return num*flag;
 29 }
 30 struct node{
 31     int l,r,mx,mn;
 32     int mid(){return (l+r)>>1;}
 33 }lst[maxm];
 34 
 35 inline int in(int x,int y){
 36     return min(x&b2,y&b2)|min(x&b3,y&b3)|min(x&b5,y&b5)|min(x&b7,y&b7)|((x&b97)&(y&b97));
 37 }
 38 inline int un(int x,int y){
 39     return max(x&b2,y&b2)|max(x&b3,y&b3)|max(x&b5,y&b5)|max(x&b7,y&b7)|((x&b97)|(y&b97));
 40 }
 41 inline int tobit(int num){
 42     int cnt,bit=0;
 43     for(int i=0;i<25&&num;i++){
 44         for(cnt=0;num%prime[i]==0;num/=prime[i]) cnt++;
 45         bit|=cnt<<bpos[i];
 46     }
 47     return bit;
 48 }
 49 inline int todig(int bit,int mod){
 50     int cnt,num=1;
 51     for(int i=0,k=0;i<4;i++){
 52         k=bit>>bpos[i];
 53         num=num*pw[i][k]%mod;
 54         bit^=k<<bpos[i];
 55     }
 56     for(int i=4;i<25;i++){
 57         if(bit&(1<<bpos[i])) num=num*prime[i]%mod;
 58     }
 59     return num;
 60 }
 61 void make(int s,int t,int now){
 62     lst[now]=(node){s,t,num[s],num[s]};
 63     if(s==t) return;
 64     int mid=lst[now].mid();
 65     make(s,mid,now<<1);
 66     make(mid+1,t,now<<1|1);
 67     lst[now].mx=un(lst[now<<1].mx,lst[now<<1|1].mx);
 68     lst[now].mn=in(lst[now<<1].mn,lst[now<<1|1].mn);
 69 }
 70 void update(int pos,int x,int now){
 71     node &nd=lst[now];
 72     if(nd.l==nd.r){
 73         nd.mx=nd.mn=x;
 74         return;
 75     }
 76     int mid=nd.mid();
 77     if(pos<=mid)update(pos,x,now<<1);
 78     else update(pos,x,now<<1|1);
 79     nd.mx=un(lst[now<<1].mx,lst[now<<1|1].mx);
 80     nd.mn=in(lst[now<<1].mn,lst[now<<1|1].mn);
 81     int t=nd.mn;
 82 }
 83 int rmax(int s,int t,int now){
 84     node &nd=lst[now];
 85     if(s<=nd.l&&t>=nd.r){
 86         return nd.mx;
 87     }
 88     int ret=0,mid=nd.mid();
 89     if(s<=mid) ret=rmax(s,t,now<<1);
 90     if(t>mid)  ret=un(ret,rmax(s,t,now<<1|1));
 91     return ret;
 92 }
 93 int rmin(int s,int t,int now){
 94     node &nd=lst[now];
 95     if(s<=nd.l&&t>=nd.r){
 96         return nd.mn;
 97     }
 98     int ret=0x7fffffff,mid=nd.mid();
 99     if(s<=mid) ret=rmin(s,t,now<<1);
100     if(t>mid)  ret=in(ret,rmin(s,t,now<<1|1));
101     return ret;
102 }
103 
104 int main(){
105 //#define test
106 #ifdef test
107     freopen("in.txt","r",stdin);
108     freopen("out.txt","w",stdout);
109 #endif
110 
111     while(~scanf("%d%d",&n,&m)){
112         for(int i=1;i<=n;i++){
113             k=read();
114             num[i]=tobit(k);
115         }
116         make(1,n,1);
117         while(m--){
118             int a,b,c=getchar();
119             while(c!='C'&&c!='L'&&c!='G'){
120                 c=getchar();
121             }
122             if(c=='C'){
123                 a=read(),b=read();
124                 update(a,tobit(b),1);
125             }else {
126                 a=read(),b=read();
127                 int ans=0;
128                 if(c=='L') ans=rmax(a,b,1);
129                 else ans=rmin(a,b,1);
130                 c=read();
131                 printf("%u\n",todig(ans,c));
132             }
133         }
134     }
135 
136 #ifdef test
137     fclose(stdin);
138   fclose(stdout);
139     system("out.txt");
140 #endif
141     return 0;
142 }
View Code

----

题已经写得差不多了,慢慢更新题解吧

转载于:https://www.cnblogs.com/nervendnig/p/8440381.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值