[BZOJ2758] [SCOI2012]Blinker的噩梦 扫描线+set
题目大意:有n个圆或凸多边形,这些图形不会相交,每当走入或走出一个图形时需要异或上一个代价,有m组操作:
询问操作,每次询问从一个点走到另一个点时,需要的代价(初始代价为0)
修改操作,每次修改一个图形的代价
数据范围:n≤1e5,点权的绝对值不大于1e9
此题真实毒瘤题
考虑到此题图形之间两两互不相交,那么图形与图形之间的关系为相离或包含,包含关系我们可以将其建成一棵树结构。
我们用set来维护一个以x为第一关键字的扫描线,每次扫描到一个新的图形,我们就将该图形拆成上下两部分(可以理解为左右括号),分别加入到set中(考虑到图形不会包含,那么在图形出现的值域内,如果只考虑当前加入的这些图形,这些图形构成的括号序列是不会发生变化的,我们只需要写一个在给定X值情况下能求出图形上下两部分的Y值的函数即可)
然后再做一条射线往上,碰到了另一个多边形,不难发现只会有两种情况:
第一种情况:遇到一个图形的上部分,那么显然碰到的那个图形包含了当前图形。
第二种情况:遇到一个图形的下部分,那么显然当前图形与碰到的图形是相离关系。
当某个图形在扫描线变化后不再出现时,从set中删去这个图形。
(以上说得有点玄乎,感性理解下吧)
我们基于这些关系,建出了一棵树。
对于一个查询操作,显然是查询从树上一个点到另一个点的异或和,考虑到这个值可能会被修改,用树状数组随便维护下就好了
然后就没了,说起来很简单写起来hhh。
注意精度损失!!!!!
#include<bits/stdc++.h>
#define M 300005
#define INF 1e15
#define eps 1e-9
#define D long double
#define sqr(x) ((x)*(x))
#define lowbit(x) ((x)&(-x))
using namespace std; int b[M]={},N,val[M]={};
void updata(int x,int k){ for(int i=x;i<=N;i+=lowbit(i)) b[i]^=k;}
int query(int x){ int k=; for(int i=x;i;i-=lowbit(i)) k^=b[i]; return k;} struct edge{int u,next;}e[M]={}; int head[M]={},use=;
void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;}
int dfn[M]={},low[M]={},fa[M]={},t=;
void dfs(int x){
dfn[x]=++t;
for(int i=head[x];i;i=e[i].next) dfs(e[i].u);
low[x]=t;
updata(dfn[x],val[x]);
updata(low[x]+,val[x]);
} D nowX; struct node{
int n,down,val,id;
D X,Y,r,x[],y[];
D lx,rx;
void makebig(){X=Y=; r=INF;lx=-INF; rx=INF;}
void rd(int ID){
id=ID;
char op[]; scanf("%s",op);
if(op[]=='C'){
n=; scanf("%Lf%Lf%Lf",&X,&Y,&r);
lx=X-r; rx=X+r;
}else{
scanf("%d",&n);
lx=INF; rx=-INF;
for(int i=;i<=n;i++){
scanf("%Lf%Lf",x+i,y+i);
lx=min(lx,x[i]);
rx=max(rx,x[i]);
}
x[n+]=x[]; y[n+]=y[];
}
scanf("%d",&val);
}
void rd(){
n=-;
scanf("%Lf%Lf",&X,&Y);
lx=rx=X;
}
D get(D now){
D Y1=INF,Y2=-INF;
if(n==-) return Y;
if(n==){
Y1=Y-sqrt(max(sqr(r)-sqr(X-now),(D)0.0));
Y2=Y+sqrt(max(sqr(r)-sqr(X-now),(D)0.0));
}else{
for(int i=;i<=n;i++){
D now1=x[i],now2=x[i+];
if(now1==now2) continue;
if(now1>now2) swap(now1,now2);
if(!(now1-eps<=now&&now<=now2+eps)) continue;
D k=(y[i+]-y[i])/(x[i+]-x[i]);
D nowy=y[i]+(now-x[i])*k;
Y1=min(Y1,nowy);
Y2=max(Y2,nowy);
}
}
if(down) return Y1;
return Y2;
}
friend bool operator <(node a,node b){
D vala=a.get(nowX);
D valb=b.get(nowX);
if(fabs(vala-valb)>eps) return vala<valb;
return a.down>b.down;
}
}a[M];
set<node> s;
int n,m,q; void pushset(node now){
now.down=; s.insert(now);
now.down=; s.insert(now);
}
void popset(node now){
now.down=; s.erase(now);
now.down=; s.erase(now);
} struct hh{
int id,zf; hh(int ID=,int ZF=){id=ID; zf=ZF;}
friend bool operator <(hh x,hh y){
D valx,valy;
if(x.zf==-) valx=a[x.id].lx; else valx=a[x.id].rx;
if(y.zf==-) valy=a[y.id].lx; else valy=a[y.id].rx;
return valx<valy;
}
}p[M*]={}; int pointsum=;
int chx[M]={},chval[M]={},id1[M]={},id2[M]={}; int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
a[].makebig(); fa[]=-;
nowX=-INF; pushset(a[]);
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++) a[++pointsum].rd(i); for(int i=;i<=n;i++) val[i]=a[i].val;
for(int i=;i<=n;i++) p[++m]=hh(i,),p[++m]=hh(i,-); for(int i=;i<=q;i++){
char op[]; scanf("%s",op);
if(op[]=='C'){scanf("%d%d",chx+i,chval+i);}
else{
a[++pointsum].rd();
p[++m]=hh(pointsum,);
id1[i]=pointsum; a[++pointsum].rd();
p[++m]=hh(pointsum,);
id2[i]=pointsum;
}
} sort(p+,p+m+);
N=m+;
for(int x=;x<=m;x++){
int id=p[x].id;
//cout<<s.size()<<endl;
if(p[x].zf==-) nowX=a[id].lx; else nowX=a[id].rx;
if(p[x].zf==-||p[x].zf==){
pushset(a[id]);
set<node>::iterator it=s.find(a[id]); it++;
if(it->down)
fa[id]=fa[it->id];
else fa[id]=it->id; if(p[x].zf==)
popset(a[id]);
}else{
popset(a[id]);
}
}
for(int i=;i<=m;i++) add(fa[i],i);
dfs();
int ans=;
for(int i=;i<=q;i++){
// if(chx[i]) continue;
if(chx[i]){
int x=chx[i],zhi=chval[i];
updata(dfn[x],val[x]);
updata(low[x]+,val[x]);
val[x]=zhi;
updata(dfn[x],val[x]);
updata(low[x]+,val[x]);
}else{
int ans1=query(dfn[id1[i]]);
int ans2=query(dfn[id2[i]]);
ans=ans^ans1^ans2;
printf("%d\n",ans);
}
}
// return 0;
}
[BZOJ2758] [SCOI2012]Blinker的噩梦 扫描线+set的更多相关文章
- BZOJ2758 : [SCOI2012]Blinker的噩梦
首先将包含关系建树. 方法是将每个图形拆成上半边和下半边,从左往右扫描线,用Splay从下到上维护扫描线上所有图形. 每次加入一个新的图形$x$的时候,看看它下方第一个图形$y$,如果$y$是上半边, ...
- BZOJ 2758 Blinker的噩梦(扫描线+熟练剖分+树状数组)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2758 题意:平面上有n个多边形(凸包和圆).任意两个多边形AB只有两种关系:(1) ...
- BZOJ2757 : [SCOI2012]Blinker的仰慕者
BZOJ AC900题纪念~~ 若K>0,则 设f[i][j]表示i位数字,积为j的数字的个数 g[i][j]表示i位数字,积为j的数字的和 DP+Hash预处理 查询时枚举LCP然后统计贡献 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- bzoj2758【scoi2012】Blinker的的噩梦
题目描述 一天Blinker醒来,发现自己成为了一个二维世界的点,而且被标记上了一个奇怪的值. 这个世界是由N个边界互不相交(且不相切)的图形组成,这里图形仅包括圆和凸多边形.每个图形还有一个权值.每 ...
- bzoj2757【scoi2012】Blinker的仰慕者
题目描述 Blinker 有非常多的仰慕者,他给每个仰慕者一个正整数编号.而且这些编号还隐藏着特殊的意义,即编号的各位数字之积表示这名仰慕者对Blinker的重要度. 现在Blinker想知道编号介于 ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3352 Solved: 919[Submit][Stat ...
- Bzoj2756 [SCOI2012]奇怪的游戏
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3220 Solved: 886 Description ...
- 【BZOJ】【2756】【SCOI2012】奇怪的游戏
网络流-最大流 这题……建模部分先略过 这道题是会卡时限的T_T俺的Dinic被卡了,在此放几篇很棒的讲网络流算法的文章,至于大家耳熟能详的论文就不放了…… http://www.cppblog.co ...
随机推荐
- 外网不能访问阿里云服务器的apache服务
今天弄了下Ubuntu的服务器,配置了一个LAMP环境的服务器,配置有时间我再来说 但是配置了很长的时间,差不都怕是好几个小时 在配置apache的时候,出现了问题,好不容易把apache服务配置好 ...
- 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)
传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...
- ThinkPHP5 union分页
直接贴代码,记录一下,备用 $a = Db::name(表名)->field(字段)->where(条件)->buildSql(); $b = Db::name(表名)->fi ...
- 浅谈OCR之Tesseract
光 学字符识别(OCR,Optical Character Recognition)是指对文本资料进行扫描,然后对图像文件进行分析处理,获取文字及版面信息的过程.OCR技术非常专业,一般多是印刷.打印 ...
- java判断字符串是否为数字,包括负数
/** * 判断是否为数字,包含负数情况 * @param str * @return */ private boolean isNumeric(String str){ Boolean flag = ...
- Python 学习目录
第一章 Python基础 第二章 Python基础 第三章 Python基础-文件操作&函数 1.python文件处理 2.py-函数基础 3.py-函数进阶 第四章 Python基础-常用模 ...
- python读写操作
import sys 1 def test(): a=int(input()) x=[int(i) for i in input().split(' ')] y=[int(j) for j in sy ...
- 大文件webuploader的基本使用
webuploader的简单使用 需要的文件 自备 百度很多 webuploader.js uploader.swf jQuery <!DOCTYPE html> <htm ...
- python Cannot uninstall 'numpy'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.
在Python中移除(升级)numpy的时候出现: Cannot uninstall 'numpy'. It is a distutils installed project and thus we ...
- 如何更新world文档的目录
在想要设置目录的文档页,右键 -> 更新域, 或者在想要设置目录的文档页,按下 F9 即可 拓展: 在目录文档页 ,按Ctrl 并且单击鼠标可以跟踪目标连接 如果内容对您有所帮助,请打赏--- ...