20230625-Segment Tree 2

20230625

知识点

  1. 基础线段树
  2. 李超线段树
  3. Segment Tree Beat
  4. 线段树的合并与分治

基础线段树

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;
}
posted @ 2023-07-19 22:43  H_W_Y  阅读(13)  评论(0编辑  收藏  举报