首先将包含关系建树。

方法是将每个图形拆成上半边和下半边,从左往右扫描线,用Splay从下到上维护扫描线上所有图形。

每次加入一个新的图形$x$的时候,看看它下方第一个图形$y$,如果$y$是上半边,那么$x$的父亲就是$y$,否则是$y$的父亲。用同样的方法可以完成点定位。

然后每次相当于查询两点间的异或和,用树状数组维护dfs序即可。

时间复杂度$O((n+m)\log n)$。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=100010,M=N*2;
const double inf=1e20;
const double eps=1e-9;
int n,m,i,x,y,val[N],ce,cb,q[N][3],ans;double X;
struct Shape{
bool type;
double x,y,r,a[35][2];
int n;
void read(){
char t[5];
scanf("%s",t);
if(t[0]=='C')type=0,scanf("%lf%lf%lf",&x,&y,&r);
else{
type=1;
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%lf%lf",&a[i][0],&a[i][1]);
a[n][0]=a[0][0],a[n][1]=a[0][1];
}
}
double getl(){
if(!type)return x-r;
double ret=inf;
for(int i=0;i<n;i++)ret=min(ret,a[i][0]);
return ret;
}
double getr(){
if(!type)return x+r;
double ret=-inf;
for(int i=0;i<n;i++)ret=max(ret,a[i][0]);
return ret;
}
double getd(double o){
if(!type)return y-sqrt(max(r*r-(o-x)*(o-x),0.0));
double ret=inf;
for(int i=0;i<n;i++){
double A=a[i][0],B=a[i][1],C=a[i+1][0],D=a[i+1][1];
if(A>C)swap(A,C),swap(B,D);
if(o<A-eps||o>C+eps)continue;
if(o<A+eps){
ret=min(ret,B);
continue;
}
if(o>C-eps){
ret=min(ret,D);
continue;
}
ret=min(ret,B+(D-B)/(C-A)*(o-A));
}
return ret;
}
double getu(double o){
if(!type)return y+sqrt(max(r*r-(o-x)*(o-x),0.0));
double ret=-inf;
for(int i=0;i<n;i++){
double A=a[i][0],B=a[i][1],C=a[i+1][0],D=a[i+1][1];
if(A>C)swap(A,C),swap(B,D);
if(o<A-eps||o>C+eps)continue;
if(o<A+eps){
ret=max(ret,B);
continue;
}
if(o>C-eps){
ret=max(ret,D);
continue;
}
ret=max(ret,B+(D-B)/(C-A)*(o-A));
}
return ret;
}
}a[N];
struct E{
double x;int y,t;
E(){}
E(double _x,int _y,int _t){x=_x,y=_y,t=_t;}
}e[N*4];
inline bool cmp(const E&a,const E&b){
if(a.t<2&&b.t<2&&a.y==b.y)return a.t<b.t;
return a.x<b.x;
}
struct P{double x,y;}b[M];
int from[M],son[M][2],f[M],root,L,R,fa[N],g[N],v[M],nxt[M],ed,st[N],en[N],dfn,bit[M];
inline void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;
if(son[z][1]==y)son[z][1]=x;
}
f[x]=f[y];son[x][w^1]=y;f[y]=x;
}
inline void splay(int x,int w){
while(f[x]!=w){
int y=f[x];
if(f[y]!=w){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}
if(!w)root=x;
}
inline bool bigger(int x,int y){
if(y==L)return 1;
if(y==R)return 0;
if(x+n==y||x==y+n)return x>y;
double A=x<=n?a[x].getd(X):a[x-n].getu(X),
B=y<=n?a[y].getd(X):a[y-n].getu(X);
return A>B;
}
inline bool biggerp(double x,int y){
if(y==L)return 1;
if(y==R)return 0;
double B=y<=n?a[y].getd(X):a[y-n].getu(X);
return x>B;
}
void ins(int x,int y){
int w=bigger(y,x);
if(!son[x][w]){son[x][w]=y;f[y]=x;return;}
ins(son[x][w],y);
}
int ask(int x,double y){
if(!x)return 0;
if(biggerp(y,x)){
int t=ask(son[x][1],y);
return t?t:x;
}
return ask(son[x][0],y);
}
inline void add(int x){
ins(root,x);
ins(root,x+n);
splay(x,0);
int y;
for(y=son[x][0];son[y][1];y=son[y][1]);
if(y<L)fa[x]=y<=n?y:fa[y-n];
splay(y,0);
}
inline void del(int x){
splay(x,0);
int y;
for(y=son[x][0];son[y][1];y=son[y][1]);
splay(y,x);
son[y][1]=son[x][1];
f[son[x][1]]=y;
f[root=y]=0;
}
inline void getpos(int x){
int y=ask(root,b[x].y);
if(y<L)from[x]=y<=n?y:fa[y-n];
splay(y,0);
}
void dfs(int x){
st[x]=++dfn;
for(int i=g[x];i;i=nxt[i])dfs(i);
en[x]=++dfn;
}
inline void modify(int x,int y){for(;x<=dfn;x+=x&-x)bit[x]^=y;}
inline int sum(int x){int t=0;for(;x;x-=x&-x)t^=bit[x];return t;}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
a[i].read();
scanf("%d",&val[i]);
e[++ce]=E(a[i].getl(),i,0);
e[++ce]=E(a[i].getr(),i,1);
}
for(i=1;i<=m;i++){
char op[5];
scanf("%s",op);
if(op[0]=='Q'){
cb++;
scanf("%lf%lf",&b[cb].x,&b[cb].y);
e[++ce]=E(b[cb].x,cb,2);
cb++;
scanf("%lf%lf",&b[cb].x,&b[cb].y);
e[++ce]=E(b[cb].x,cb,2);
q[i][1]=cb-1,q[i][2]=cb;
}else{
q[i][0]=1;
scanf("%d%d",&q[i][1],&q[i][2]);
}
}
sort(e+1,e+ce+1,cmp);
L=n*2+1;R=L+1;
son[L][1]=R,f[R]=L;
root=L;
for(i=1;i<=ce;i++){
X=e[i].x;
if(!e[i].t)add(e[i].y);
else if(e[i].t==1)del(e[i].y),del(e[i].y+n);
else getpos(e[i].y);
}
for(i=1;i<=n;i++)if(fa[i])nxt[i]=g[fa[i]],g[fa[i]]=i;
for(i=1;i<=n;i++)if(!fa[i])dfs(i);
for(i=1;i<=n;i++)modify(st[i],val[i]),modify(en[i],val[i]);
for(i=1;i<=m;i++)if(q[i][0]){
x=q[i][1],y=q[i][2]^val[x];
val[x]=q[i][2];
modify(st[x],y),modify(en[x],y);
}else printf("%d\n",ans^=sum(st[from[q[i][1]]])^sum(st[from[q[i][2]]]));
return 0;
}

  

BZOJ2758 : [SCOI2012]Blinker的噩梦的更多相关文章

  1. [BZOJ2758] [SCOI2012]Blinker的噩梦 扫描线+set

    题目大意:有n个圆或凸多边形,这些图形不会相交,每当走入或走出一个图形时需要异或上一个代价,有m组操作: 询问操作,每次询问从一个点走到另一个点时,需要的代价(初始代价为0) 修改操作,每次修改一个图 ...

  2. BZOJ2757 : [SCOI2012]Blinker的仰慕者

    BZOJ AC900题纪念~~ 若K>0,则 设f[i][j]表示i位数字,积为j的数字的个数 g[i][j]表示i位数字,积为j的数字的和 DP+Hash预处理 查询时枚举LCP然后统计贡献 ...

  3. BZOJ 2758 Blinker的噩梦(扫描线+熟练剖分+树状数组)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2758 题意:平面上有n个多边形(凸包和圆).任意两个多边形AB只有两种关系:(1) ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. bzoj2758【scoi2012】Blinker的的噩梦

    题目描述 一天Blinker醒来,发现自己成为了一个二维世界的点,而且被标记上了一个奇怪的值. 这个世界是由N个边界互不相交(且不相切)的图形组成,这里图形仅包括圆和凸多边形.每个图形还有一个权值.每 ...

  6. bzoj2757【scoi2012】Blinker的仰慕者

    题目描述 Blinker 有非常多的仰慕者,他给每个仰慕者一个正整数编号.而且这些编号还隐藏着特殊的意义,即编号的各位数字之积表示这名仰慕者对Blinker的重要度. 现在Blinker想知道编号介于 ...

  7. BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3352  Solved: 919[Submit][Stat ...

  8. Bzoj2756 [SCOI2012]奇怪的游戏

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3220  Solved: 886 Description ...

  9. 【BZOJ】【2756】【SCOI2012】奇怪的游戏

    网络流-最大流 这题……建模部分先略过 这道题是会卡时限的T_T俺的Dinic被卡了,在此放几篇很棒的讲网络流算法的文章,至于大家耳熟能详的论文就不放了…… http://www.cppblog.co ...

随机推荐

  1. tomcat和apache区别联系

    tomcat和apache区别联系 Apache是普通服务器,本身只支持html即普通网页.不过可以通过插件支持php,还可以与Tomcat连通(单向Apache连接Tomcat, 就是说通过Apac ...

  2. 几年前做家教写的C教程(之二)

    C语言学习宝典(2) 认识C语言中的运算符: (1)算术运算符   (+  -  *  /  %) (2)关系运算符    (>  <  ==  >=  <=  != ) (3 ...

  3. python列表分组的技巧

    今天项目上需要到的. 如,将并行部署的机器分批次. 一次十台机器,如果分3次并行部署,则第一次123,第二次456,第三次789,第四次10. #coding=utf-8 a=[1,2,3,4,5,6 ...

  4. javascript实用技巧,js小知识

    一.js整数的操作 使用|0和~~可以将浮点转成整型且效率方面要比同类的parseInt,Math.round 要快,在处理像素及动画位移等效果的时候会很有用.性能比较见此. var foo = (1 ...

  5. HTTPCLIENT 学习 (1) 入门

    早就如雷贯耳它的大名,却一直不曾相见,昨天下载下来,今天终于测试了一把,用的官网的QUICK START例子,来访问我自己以前开发过的WEB程序,因为这个网站恰好有一个写好的通过POST请求验证用户名 ...

  6. golang time and duration

    package mainimport "fmt"import "time"func main() { p := fmt.Println // We'll sta ...

  7. VS2015上又一必备免费插件:Refactoring Essentials

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:Refactoring Essentials是一款用于代码分析和重构的开源免费VS20 ...

  8. RTP RTCP在音视频传输与同步方面的使用

    转自:http://blog.csdn.net/kof98765/article/details/17733701 1 音视频实时传输 1.1 Jrtplib库介绍 本系统采用开源库Jrtplib进行 ...

  9. Sizeof与Strlen的区别与联系

    转自:http://www.cnblogs.com/carekee/articles/1630789.html 一.sizeof    sizeof(...)是运算符,在头文件中typedef为uns ...

  10. 轻松搞定javascript预解析机制(搞定后,一切有关变态面试题都是浮云~~)

    hey,guys!我们一起总结一下JS预解析吧! 首先,我们得搞清楚JS预解析和JS逐行执行的关系.其实它们两并不冲突,一个例子轻松理解它们的关系: 你去酒店吃饭,吃饭前你得看下菜谱,点下菜(JS预解 ...