【NOI2017模拟4.2】查询【线段树】
来源:互联网 发布:eureka java demo 编辑:程序博客网 时间:2024/04/30 14:05
Description
给出若干条线段,用(x1,y1),(x2,y2)表示其两端点坐标,现在要求支持两种操作:
0 x1 y1 x2 y2
表示加入一条新的线段,(x1,y1)-(x2,y2)
1 x0
询问所有线段中,x坐标在x0处的最高点的y坐标是什么,如果对应位置没有线段,则输出0。
Solution
这题一看就是用线段树做的。但是问题就是怎么维护。
很明显我们要在区间维护一条直线。
但是如果有一条直线交了过去该怎么办?
假设我们现在要修改[l,r]这个区间,我们先在线段树上找到对应的子区间,然后这个子区间会有一条线段。
假设我们当前的线段可以完全高于这个区间上的线段,那么直接更新这个值。
否则:
我们设当前这条线段为a,区间维护的线段为b
如果mid在交点的左边:如果a在[l,mid]可以覆盖,那么把a和b交换(就是把当前线段改为b,维护线段改为a),然后向右继续搜。如果在[l,mid]没有覆盖,那么直接往右搜。
如果mid在交点的右边:如果a在[mid+1,r]可以覆盖,那么把a和b交换,然后向左继续搜。如果在[mid+1,r]没有覆盖,那么直接往左搜。
这样的时间复杂度是
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=2e5+7,mxx=1e6+maxn,inf=0x7fffffff;typedef double db;struct nod{ db p,q;}t[mxx*4];int i,j,k,l,n,m,num,x,y,xx,yy,ha,da;bool bz[maxn];db ans,kk,o,yi,er;void change(int x,int l,int r,int y,int z,db p,db q){ if(l==y&&r==z){ if(x==1572969){ o=o; } if(l==r||(db)(t[x].p-p)*(t[x].p+(r-l)*t[x].q-p-(r-l)*q)>0.0){ if(p>t[x].p)t[x].p=p,t[x].q=q; return; } int mid=(l+r)/2; yi=(db)t[x].p+(mid-l)*t[x].q; er=(db)p+(mid-l)*q; if((t[x].p-p)*(yi-er)>0){ if(er>yi){ swap(t[x].p,p),swap(t[x].q,q); change(x*2+1,mid+1,r,mid+1,z,p+q*(mid-y+1),q); } else{ change(x*2+1,mid+1,r,mid+1,z,p+q*(mid-y+1),q); } } else{ if(er>yi){ swap(t[x].p,p),swap(t[x].q,q); change(x*2,l,mid,y,mid,p,q); } else{ change(x*2,l,mid,y,mid,p,q); // change(x*2+1,mid+1,r,mid+1,z,p+q*(mid-y+1),q); } } return; } int mid=(l+r)/2; if(z<=mid)change(x*2,l,mid,y,z,p,q); else if(y>mid)change(x*2+1,mid+1,r,y,z,p,q); else{ change(x*2,l,mid,y,mid,p,q); change(x*2+1,mid+1,r,mid+1,z,p+q*(mid-y+1),q); }}void find(int x,int l,int r,int y){ ans=max(ans,t[x].p+(y-l)*t[x].q); if(l==r){ return; } int mid=(l+r)/2; if(y<=mid)find(x*2,l,mid,y); else find(x*2+1,mid+1,r,y);}int main(){ freopen("query.in","r",stdin); freopen("query.out","w",stdout);// freopen("fan.in","r",stdin);// freopen("fan.out","w",stdout); scanf("%d%d",&n,&m);da=1000001; fo(i,0,mxx*4-1)t[i].p=-9999999999; fo(i,1,n){ scanf("%d%d%d%d",&x,&y,&xx,&yy); if(x>xx)swap(x,xx),swap(y,yy); if(x==xx&&y>yy)swap(y,yy); x+=da,xx+=da;ha=x; if(xx==x)kk=inf;else kk=(db)(yy-y)/(xx-x); if(kk==inf)y=yy,kk=0; change(1,1,2*da,x,xx,y,kk); } fo(i,1,m){ scanf("%d",&k); if(k==0){ scanf("%d%d%d%d",&x,&y,&xx,&yy); if(x>xx)swap(x,xx),swap(y,yy); if(x==xx&&y>yy)swap(y,yy); if(x==180){ k=k; } x+=da,xx+=da;ha=x; if(xx==x)kk=inf;else kk=(db)(yy-y)/(xx-x); if(kk==inf)y=yy,kk=0; change(1,1,2*da,x,xx,y,kk); } else{ scanf("%d",&x); x+=da; ans=-9999999999; find(1,1,2*da,x); if(ans==-9999999999)ans=0; printf("%.6lf\n",ans); } }}
1 0
- 【NOI2017模拟4.2】查询【线段树】
- jzoj 5039. 【NOI2017模拟4.2】查询 线段树
- 【NOI2017模拟4.2】查询
- 【JZOJ5039】【NOI2017模拟4.2】查询
- jzoj 5020. 【NOI2017模拟3.17】牛奶装瓶 线段树
- 【NOI2017模拟4.2】押韵
- 【JZOJ5040】【NOI2017模拟4.2】押韵
- jzoj 5040. 【NOI2017模拟4.2】押韵 trie树+树形dp
- NOI2017模拟3.1 总结
- NOI2017模拟3.8 总结
- 【NOI2017模拟3.30】原谅
- 【NOI2017模拟6.26】A
- 【NOI2017模拟6.29】呵呵
- 【NOI2017模拟6.2】字符串
- [线段树维护BITSET] NOI2017 .Day1 T1 整数
- jzoj 5001. 【NOI2017模拟3.4】Trie树 状压dp
- jzoj 5015. 【NOI2017模拟3.15】决斗 贪心+平衡树
- 【JZOJ5037】【NOI2017模拟3.30】轮回
- hashcode
- 一.配置简单的嵌入式tomcat和jetty
- Mybatis和Spring项目突然报错
- Android开发学习笔记(4)
- 数组算法时间复杂度
- 【NOI2017模拟4.2】查询【线段树】
- Python 实现二叉树相关操作
- OpenGL配置.NET平台
- No mapping found for HTTP request with URI [/exam3/welcome.do] in DispatcherServlet with name 'XXX'
- python的import与from...import的不同之处
- 大话设计模式读书笔记(五) 代理模式
- 深度机器学习中的batch的大小对学习效果有何影响?
- BZOJ P3294[Cqoi2011]放棋子
- 全排列 next_permutation