20230625-Segment Tree 2
20230625
知识点
- 基础线段树
- 李超线段树
- Segment Tree Beat
- 线段树的合并与分治
基础线段树
CF840D Destiny
题目描述
传送门
简单易懂
Solution
我看了题甚至直接联想到了摩尔投票法……
发现其实就是一个主席树
数组不要开小了!!!
我们维护一个可持久化线段树记录每一个数字出现的次数即可
查询时类似二分去找即可
和这道题是相当像的
H_W_Y-Coding
#include <bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define lc tr[p].ch[0]
#define rc tr[p].ch[1]
#define ls tr[pre].ch[0]
#define rs tr[pre].ch[1]
const int N=5e5+10,inf=0x3f3f3f3f;
int n,m,rt[N],a[N],l,r,k,cnt=0,res;
bool flag=false;
struct seg{
int sum,ch[2];
}tr[N<<5];
void update(int &p,int pre,int l,int r,int x){
p=++cnt;
tr[p]=tr[pre];
tr[p].sum++;
if(l==r) return;
if(x<=mid) update(lc,ls,l,mid,x);
else update(rc,rs,mid+1,r,x);
}
int query(int p,int pre,int l,int r,int k){
if(l==r) return l;
int lsum=tr[lc].sum-tr[ls].sum,rsum=tr[rc].sum-tr[rs].sum,res;
if(lsum>=k) if((res=query(lc,ls,l,mid,k))>0) return res;
if(rsum>=k) if((res=query(rc,rs,mid+1,r,k))>0) return res;
return -1;
}
int main(){
/*2023.7.28 H_W_Y CF840D Destiny 可持久化线段树*/
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
update(rt[i],rt[i-1],1,n,a[i]);
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l,&r,&k);
k=((r-l+1)/k)+1;
printf("%d\n",query(rt[r],rt[l-1],1,n,k));
}
return 0;
}
李超线段树
P4097 [HEOI2013] Segment
题目描述
传送门
简单易懂
Solution
李超线段树的模板题
注意double的比较都要用cmp
这道题要加上线段编号的比较
H_W_Y-Coding
#include<bits/stdc++.h>
using namespace std;
#define pp pair<double,int>
const double eps=1e-8;
const int N=1e5+5,mod1=39989,mod2=1e9;
int n,tr[N<<2],cnt=0,lst=0;
struct lne{
double k,b;
}l[N];
void build(int X1,int Y1,int X2,int Y2){
cnt++;
if(X1==X2) l[cnt]=(lne){0,1.0*max(Y1,Y2)};
else l[cnt].k=1.0*(Y1-Y2)/(X1-X2),l[cnt].b=1.0*(Y1-l[cnt].k*X1);
}
int cmp(double p){return p<-eps?-1:(p>eps?1:0);}
double calc(int x,int k){return 1.0*l[k].k*x+l[k].b;}
pp pmax(pp x,pp y){
if(cmp(x.first-y.first)==1) return x;
if(cmp(x.first-y.first)==-1) return y;
return x.second<y.second?x:y;
}
#define mid (l+r)/2
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
void add(int l,int r,int rt,int u){
int &v=tr[rt];
int bmid=cmp(calc(mid,u)-calc(mid,v));
if(bmid==1||(!bmid&&u<v)) swap(u,v);
int bl=cmp(calc(l,u)-calc(l,v)),br=cmp(calc(r,u)-calc(r,v));
if(bl==1||(!bl&&u<v)) add(lson,u);
if(br==1||(!br&&u<v)) add(rson,u);
}
void update(int l,int r,int rt,int a,int b,int x){
if(a<=l&&b>=r){
add(l,r,rt,x);
return ;
}
if(a<=mid) update(lson,a,b,x);
if(b>mid) update(rson,a,b,x);
}
pp query(int l,int r,int rt,int x){
if(r<x||l>x) return {0,0};
double res=calc(x,tr[rt]);
if(l==r) return {res,tr[rt]};
return pmax({res,tr[rt]},pmax(query(lson,x),query(rson,x)));
}
int main(){
/*2023.7.28 H_W_Y P4097 [HEOI2013] Segment 李超线段树*/
scanf("%d",&n);
for(int i=1,op;i<=n;i++){
scanf("%d",&op);
if(op==1){
int X2,X1,Y1,Y2;
scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
X1=(X1+lst-1+mod1)%mod1+1;X2=(X2+lst-1+mod1)%mod1+1;
Y1=(Y1+lst-1+mod2)%mod2+1;Y2=(Y2+lst-1+mod2)%mod2+1;
if(X1>X2) swap(X1,X2),swap(Y1,Y2);
build(X1,Y1,X2,Y2);
update(1,mod1,1,X1,X2,cnt);
}
else {
int x;scanf("%d",&x);
printf("%d\n",lst=query(1,mod1,1,(x+lst-1+mod1)%mod1+1).second);
}
}
return 0;
}