线段树树套树杭电ojLuck and Love
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树树套树杭电ojLuck and Love相关的知识,希望对你有一定的参考价值。
- 博客主页: https://blog.csdn.net/qq_50285142
- 欢迎点赞👍收藏✨关注❤留言 📝 如有错误,敬请指正
- 🎈虽然生活很难,但我们也要一直走下去🎈
题目链接
思路:
问题是要询问满足两个区间的最大缘分值,因为一个树只能记录一个区间,我们只能再弄个树,所以就是树套树了。同时还要记录最大值。
主树记录身高这个区间,附树记录活泼度这个区间,同时记录最大值。
每个线段树节点都要声明一颗线段树,来记录满足身高区间内的其它情况。
所以都要有两个函数,一个是主树的,一个是附树的。
建树思路和单个基本一样,就是在访问每个主线段树节点时,都要对每个节点上的子线段树进行操作。
同时注意初始化-1
,而且变量记录的可能比较多
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
const int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const int mod = 1e9+7;
const int N = 100,M = 1000;
int n,m,k;
struct son
{
int l,r;
int mx;
};//附树
struct parent
{
int l,r;
son so[M*4];
}tr[N*4];//主树
//主线段树的节点,子线段树访问到的节点,子线段树左区间,右区间
void sbuild(int root,int u,int l,int r)
{
tr[root].so[u] = {l,r,-1};
if(l==r) return ;
int mid = l + r >> 1;
sbuild(root,u<<1,l,mid);
sbuild(root,u<<1|1,mid+1,r);
}
//主线段树的节点,身高区间,活泼度区间
void build(int u,int l1,int r1,int l2,int r2)
{
tr[u] = {l1,r1};
sbuild(u,1,l2,r2);
if(l1==r1) return ;
int mid = l1 + r1 >> 1;
build(u<<1,l1,mid,l2,r2);
build(u<<1|1,mid+1,r1,l2,r2);
}
//主线段树的节点,子线段树访问到的节点,活泼度,缘分值
void smodify(int root,int u,int a,int v)
{
if(tr[root].so[u].l == a && tr[root].so[u].r==a)
{
//可能有多个相同活泼度的值,但缘分值不同,所以要取max
tr[root].so[u].mx = max(tr[root].so[u].mx,v);
return;
}
int mid = tr[root].so[u].l + tr[root].so[u].r >> 1;
if(a <= mid) smodify(root,u<<1,a,v);
else smodify(root,u<<1|1,a,v);
//修改完要进行pushup操作
tr[root].so[u].mx = max(tr[root].so[u<<1].mx,tr[root].so[u<<1|1].mx);
}
//主线段树的节点,身高,活泼度,缘分值
void modify(int u,int h,int a,int v)
{
//主树只记录一个身高区间,只需查区间即可
smodify(u,1,a,v);
if(tr[u].l == h && tr[u].r == h) return;
int mid = tr[u].l + tr[u].r >> 1;
if(h <= mid) modify(u<<1,h,a,v);
else modify(u<<1|1,h,a,v);
}
//主线段树的位于的节点,子线段树访问到的节点,活泼度区间
int squery(int root,int u,int l,int r)
{
if(tr[root].so[u].l>=l && tr[root].so[u].r <=r)
return tr[root].so[u].mx;
int mid = tr[root].so[u].l + tr[root].so[u].r >> 1;
int res = -1;
if(l <= mid) res = max(res,squery(root,u<<1,l,r));
if(r > mid) res = max(res,squery(root,u<<1|1,l,r));
return res;
}
//主线段树的节点,身高区间,活泼度区间
int query(int u,int l1,int r1,int l2,int r2)
{
if(tr[u].l >= l1 && tr[u].r <= r1)
return squery(u,1,l2,r2);
int mid = tr[u].l + tr[u].r >> 1;
int res = -1;
if(l1 <= mid) res = max(res,query(u<<1,l1,r1,l2,r2));
if(r1 > mid) res = max(res,query(u<<1|1,l1,r1,l2,r2));
return res;
}
void solve()
{
int h,h1,h2;
double a,l,a1,a2;
while(scanf("%d",&n) and n)
{
build(1,100,200,0,1000);
while(n--)
{
char s[2];
scanf("%s",s);
if(*s=='I')
{
scanf("%d %lf %lf",&h,&a,&l);
modify(1,h,(int)(a*10),(int)(l*10));
}
else
{
scanf("%d %d %lf %lf",&h1,&h2,&a1,&a2);
if(h1>h2) swap(h1,h2);
if(a1>a2) swap(a1,a2);
int ans = query(1,h1,h2,(int)(a1*10),(int)(a2*10));
if(ans<0) printf("-1\\n");
else printf("%.1lf\\n",ans/10.0);
}
}
}
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0),cout.tie(0);
int _;
// cin>>_;
_ = 1;
while(_--)
{
solve();
}
return 0;
}
往期优质文章推荐
以上是关于线段树树套树杭电ojLuck and Love的主要内容,如果未能解决你的问题,请参考以下文章