[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 ...
随机推荐
- 2018.10.16 NOIP模拟 长者(主席树+hash)
传送门 考试的时候开始sb的以为需要可持久化trietrietrie树,发现建树时空都是O(n2)O(n^2)O(n2)的. 然后发现由于每次只从原来的字符串改一个字符. 因此直接主席树维护区间has ...
- 2018.07.06 POJ1556 The Doors(最短路)
The Doors Time Limit: 1000MS Memory Limit: 10000K Description You are to find the length of the shor ...
- SQL查询优化的一些建议
使用批量查询,而不是N次循环查询! 重复的数据,不要重复获取: 根据需要,按需要获取表字段,而不是SELECT *: 针对频繁的搜索字段,建立必要的索引,以加快查询速度: 使用关联查询,而不是粗暴地类 ...
- An existing resource has been found at location D:\Tomcat 7\apache-tomcat-7.0.55\webapps。。。
这个错误是说你的资源丢失,就是说tomcat无法解析你的.class文件,需要自己重新配置一下. 解决方法: 右击项目名 ---> 点击properties --> 在搜索栏里 输入 WE ...
- I2C笔记
SCL:上升沿将数据输入到每个EEPROM器件中:下降沿驱动EEPROM器件输出数据.(边沿触发) SDA:双向数据线,为OD门,与其它任意数量的OD与OC门成"线与"关系. ...
- codeforces 702C Cellular Network 2016-10-15 18:19 104人阅读 评论(0) 收藏
C. Cellular Network time limit per test 3 seconds memory limit per test 256 megabytes input standard ...
- HDU1258 Sum It Up(DFS) 2016-07-24 14:32 57人阅读 评论(0) 收藏
Sum It Up Problem Description Given a specified total t and a list of n integers, find all distinct ...
- hdu 1877
题目 一个进制转换的题,注意0+0的情况 代码如下: #include <cstdio> int d[1000]; void solve(int n,int base) { int p = ...
- 西邮Linux兴趣小组2014级免试挑战题
原文链接:西邮Linux兴趣小组2014级免试挑战题 又到了小组纳新的季节^_^,时间过的真快! 想起去年这会儿自己做免试题的时候根本找不着北@_@ 有幸今年能够在这里和大家分享免试挑战题,也正如我 ...
- setTimeout问题
function fn(argu1){ alert(argu1); } setTimeout(fn, 1000, 12); setTimeout从第三个参数开始,之后的参数都是fn的.fn不用加(), ...