jzoj 4996. 【NOI2017模拟3.1】游戏 扫描线+treap
来源:互联网 发布:linux命令怎么退出vi 编辑:程序博客网 时间:2024/05/16 04:39
题意
在无聊的时候,小K和小H会在纸上玩这样一个游戏。
我们可以将纸看做一个平面直角坐标系。小H会先在上面画出n个圆,并把每个圆的圆心以及半径都告诉小K。小H画的n个圆中,任意两个圆不会出现相交或相切的情况。小K需要做的就是从这n个圆中选出若干个圆,使得选出的任意一个圆都不被另一个选出的圆包含。游戏的目标就是要选出尽量多的圆。
游戏一次一次进行着,小K已经对游戏的规则感到了厌倦,所以他决定修改游戏的规则。对于第i个圆,我们定义它的价值为wi。新的游戏目标是使得选出的圆价值和最大(不一定数量最多)。但是圆圈可能很多,或者圆圈的分布非常奇怪,或者小K还有别的事情要做。所以他只好拜托你来帮他求出这个最大值了。
n<=100000
分析
一看就是某种神奇的数据结构题,但是没想到要怎么求包含每个圆的第一个圆。
看了题解才想起了扫描线这种东西2333
就是每个圆在x-r和x+r处拆为两个操作,分别是插入和删除。同时把每个圆分成上半圆和下半圆,然后用一棵treap维护每个半圆。每个节点记录两个值,属于哪个圆和是上半圆还是下半圆,然后根据y值排序。每次插入一个圆后查找其下半圆的后继,若为下半圆则这个圆即为其包含圆;若为上半圆则这两个圆的包含圆相同。
treap打的我生无可恋,看来以后还是要多打treap才行。
记住以后类似于这题这样的平面+数据结构题可以用扫描线做。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<ctime>#include<cmath>#define N 100005#define LL long longusing namespace std;int n,last[N],sz,tot,mx[N],fa[N],now,root,cnt,d[N];struct edge{int to,next;}e[N];struct cyc{int x,y,r,w;}c[N];struct tree{int l,r,fix,id,op;}t[N*2];struct query{int id,val,x;}q[N*2];int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}bool cmp(query a,query b){ return a.x<b.x;}bool cmpc(cyc a,cyc b){ return a.r<b.r;}int newnode(int id,int op){ t[++sz].id=id;t[sz].op=op;t[sz].fix=rand(); return sz;}LL sqr(int x){ return (LL)x*x;}double get_y(int i,int op){ if (op==0) return (double)1.0*sqrt(sqr(c[i].r)-sqr(c[i].x-now))+(double)c[i].y; else return (double)c[i].y-(double)1.0*sqrt(sqr(c[i].r)-sqr(c[i].x-now));}void rttr(int &x){ int y=t[x].l; t[x].l=t[y].r; t[y].r=x; x=y;}void rttl(int &x){ int y=t[x].r; t[x].r=t[y].l; t[y].l=x; x=y;}void ins(int &d,int id,int op,double y){ if (!d) { d=newnode(id,op); return; } double w=get_y(t[d].id,t[d].op); if (y>w||y==w&&op<t[d].op) { ins(t[d].l,id,op,y); if (t[t[d].l].fix<t[d].fix) rttr(d); } else { ins(t[d].r,id,op,y); if (t[t[d].r].fix>t[d].fix) rttl(d); }}int findnext(int id,int op,double y){ int x=root,fa=0; while (x) { double w=get_y(t[x].id,t[x].op); if (y>w||y==w&&op<t[x].op) fa=x,x=t[x].l; else x=t[x].r; } return fa;}void del(int &d,int id,int op,double y){ if (!d) return; if (t[d].id!=id||t[d].op!=op) { double w=get_y(t[d].id,t[d].op); if (y>w||y==w&&op<t[d].op) del(t[d].l,id,op,y); else del(t[d].r,id,op,y); } else { if (!t[d].l||!t[d].r) { d=t[d].l+t[d].r;return; } if (t[t[d].l].fix<t[t[d].r].fix) rttr(d),del(t[d].r,id,op,y); else rttl(d),del(t[d].l,id,op,y); }}void addedge(int u,int v){ e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;}int main(){ //freopen("circle.in","r",stdin); //freopen("circle.out","w",stdout); srand((unsigned)time(NULL)); n=read(); for (int i=1;i<=n;i++) { c[i].x=read();c[i].y=read();c[i].r=read();c[i].w=read(); } sort(c+1,c+n+1,cmpc); for (int i=1;i<=n;i++) { q[++tot].x=c[i].x-c[i].r;q[tot].id=i;q[tot].val=1; q[++tot].x=c[i].x+c[i].r;q[tot].id=i;q[tot].val=-1; } sort(q+1,q+tot+1,cmp); for (int i=1;i<=tot;i++) { now=q[i].x; if (q[i].val==1) { ins(root,q[i].id,0,get_y(q[i].id,0)),ins(root,q[i].id,1,get_y(q[i].id,1)); int w=findnext(q[i].id,1,get_y(q[i].id,1)); if (w) { if (t[w].op==0) fa[q[i].id]=fa[t[w].id]; else fa[q[i].id]=t[w].id; } } else del(root,q[i].id,0,get_y(q[i].id,0)),del(root,q[i].id,1,get_y(q[i].id,1)); } for (int i=1;i<=n;i++) if (fa[i]) addedge(fa[i],i),d[i]++; int ans=0; for (int i=1;i<=n;i++) { for (int j=last[i];j;j=e[j].next) mx[i]+=mx[e[j].to]; mx[i]=max(mx[i],c[i].w); if (!d[i]) ans+=mx[i]; } printf("%d",ans); return 0;}
0 0
- jzoj 4996. 【NOI2017模拟3.1】游戏 扫描线+treap
- 【JZOJ 100019】【NOI2017模拟6.26】A
- JZOJ 100019【NOI2017模拟6.26】A
- JZOJ 5043. 【NOI2017模拟4.4】保持平衡
- 【NOI2017模拟4.5】机器人游戏
- NOI2017模拟3.1 总结
- jzoj 5000. 【NOI2017模拟3.4】保镖 hall定理+搜索
- jzoj 5001. 【NOI2017模拟3.4】Trie树 状压dp
- jzoj 5006. 【NOI2017模拟3.8】A 树形dp
- jzoj 5012. 【NOI2017模拟3.13】远行 启发式合并
- jzoj 5015. 【NOI2017模拟3.15】决斗 贪心+平衡树
- jzoj 5020. 【NOI2017模拟3.17】牛奶装瓶 线段树
- jzoj 5023. 【NOI2017模拟3.18】Squence 莫队算法
- jzoj 5039. 【NOI2017模拟4.2】查询 线段树
- jzoj 5040. 【NOI2017模拟4.2】押韵 trie树+树形dp
- jzoj 5045. 【NOI2017模拟4.5】无限棋盘 hash+倍增
- 【JZOJ5046】【NOI2017模拟4.5】机器人游戏
- 【NOI2017模拟4.5】机器人游戏【搜索,DP】
- springmvc 加载流程
- Kotllin与Maven和Gradle的集成
- Spring解析子元素constructor-arg
- SDNU——OJ——1016矩形合并
- 机器学习笔记6
- jzoj 4996. 【NOI2017模拟3.1】游戏 扫描线+treap
- BeanUtils组件
- 什么是分布式系统
- 蓝桥杯算法训练——安慰奶牛(最小生成树+kruskal)
- kafka与RocketMQ对比
- JS实现双击内容变为可编辑状态
- Tesseract OCR to Page (TPT) and Page Viewer (PVT)
- 3月2日,helloworld,每日20行。
- 大学思科网络技术知识点