题目链接
- 博客主页: https://blog.csdn.net/qq_50285142
- 欢迎点赞收藏✨关注❤留言 如有错误,敬请指正
- 虽然生活很难,但我们也要一直走下去
思路:
问题是要询问满足两个区间的最大缘分值,因为一个树只能记录一个区间,我们只能再弄个树,所以就是树套树了。同时还要记录最大值。
主树记录身高这个区间,附树记录活泼度这个区间,同时记录最大值。
每个线段树节点都要声明一颗线段树,来记录满足身高区间内的其它情况。
所以都要有两个函数,一个是主树的,一个是附树的。
建树思路和单个基本一样,就是在访问每个主线段树节点时,都要对每个节点上的子线段树进行操作。
同时注意初始化-1,而且变量记录的可能比较多
#include往期优质文章推荐#define fi first #define se second using namespace std; typedef long long ll; typedef pair pii; typedef pair pll; typedef vector vi; typedef vector 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("-1n"); else printf("%.1lfn",ans/10.0); } } } } int main() { // ios::sync_with_stdio(false); // cin.tie(0),cout.tie(0); int _; // cin>>_; _ = 1; while(_--) { solve(); } return 0; }
- C++ STL详解,超全总结(快速入门STL)
- 李【期末复习】c++知识点大回顾,八篇文章让你永不破防(一)
- 区间贡献问题习题详解



