题意:
给你n个不相交的凸多边形或圆,每个图形有一个权值。
询问m次,从一个点到另一个点,穿越过的图形的权值异或和。
题解:
扫描线+树链剖分。
这些图形的互相包含关系形成了一些树。
每次相当于求从树上一个点走到另一个点边上的权值异或和。
扫描线算法$O(nlgn)$求出这颗树,然后树链剖分维护下就好了。
代码:
/**************************************************************
Problem: 2758
User: yanba
Language: C++
Result: Accepted
Time:6216 ms
Memory:44112 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
int n,m;
typedef long double ld;
typedef long long LL;
char s[10];
ld now;
struct Point{
ld x,y;
Point(ld a=0,ld b=0){
x=a,y=b;
}
void read(){
double a,b;
scanf("%lf%lf",&a,&b);
x=a,y=b;
}
friend bool operator < (const Point&a,const Point &b){
return a.x<b.x;
}
}tmp[50];
struct Poly{
int id;ld lft,rgt;
vector<Point> up,down;
void read(int x){
id=x;
int num;
scanf("%d",&num);
for(int i=0;i<num;i++) tmp[i].read();
ld mn=1e200;
int pos;
for(int i=0;i<num;i++) if(tmp[i].x<mn){
mn=tmp[i].x;
pos=i;
}
lft=mn;
// puts("HAHA");
int last;
for(int i=pos;tmp[(i+1)%num].x+1e-10>tmp[i%num].x;i++){
//puts("HEHE");
last=i;
if(!up.size()){
up.push_back(tmp[i%num]);
continue;
}else{
if(fabs(tmp[i%num].x-up[up.size()-1].x)<1e-10){
up[up.size()-1].y=max(up[up.size()-1].y,tmp[i%num].y);
}else{
up.push_back(tmp[i%num]);
}
}
}
int i=last+1;
if(!up.size()){
up.push_back(tmp[i%num]);
}else{
if(fabs(tmp[i%num].x-up[up.size()-1].x)<1e-10){
up[up.size()-1].y=max(up[up.size()-1].y,tmp[i%num].y);
}else{
up.push_back(tmp[i%num]);
}
}
//puts("zzz");
// printf("%u\n",up.size());
rgt=up[up.size()-1].x;
mn=-1e200;
for(int i=0;i<num;i++) if(tmp[i].x>mn){
mn=tmp[i].x;
pos=i;
}
// puts("HEHE");
// printf("!! %d\n",id);
// printf("%d\n",pos);
for(int i=pos;tmp[(i+1)%num].x<tmp[i%num].x+1e-10;i++){
// printf("d\n",i);
last=i;
if(!down.size()){
down.push_back(tmp[i%num]);
continue;
}else{
if(fabs(tmp[i%num].x-down[down.size()-1].x)<1e-10){
down[down.size()-1].y=min(down[down.size()-1].y,tmp[i%num].y);
}else{
down.push_back(tmp[i%num]);
}
}
}
i=last+1;
if(!down.size()){
down.push_back(tmp[i%num]);
}else{
if(fabs(tmp[i%num].x-down[down.size()-1].x)<1e-10){
down[down.size()-1].y=min(down[down.size()-1].y,tmp[i%num].y);
}else{
down.push_back(tmp[i%num]);
}
}
reverse(down.begin(),down.end());
}
ld calcup(){//x=now
Point p(now-1e-8,0);
int pos=upper_bound(up.begin(),up.end(),p)-up.begin();
if(pos==0) pos++;
if(pos>=up.end()-up.begin()) pos--;
// pos-1 pos now
return (up[pos].y-up[pos-1].y)*(now-up[pos-1].x)/(up[pos].x-up[pos-1].x)+up[pos-1].y;
}
ld calcdown(){//x=now
Point p(now-1e-8,0);
int pos=upper_bound(down.begin(),down.end(),p)-down.begin();
// printf("# %d\n",pos);
if(pos==0) pos++;
// printf("# %u\n",down.end()-down.begin());
if(pos>=down.end()-down.begin()) pos--;
// printf("@@@ %.2f\n",(double)now);
// printf("%.2f %.2f\n",(double)lft,(double)rgt);
// pos-1 pos now
return (down[pos].y-down[pos-1].y)*(now-down[pos-1].x)/(down[pos].x-down[pos-1].x)+down[pos-1].y-1e-10;
}
}p[100005];
struct Cir{
int id;
Point c;
ld lft,rgt;
ld r;
void read(int x){
id=x;
c.read();
double R;
scanf("%lf",&R);
r=R+1e-8;
lft=c.x-R;
rgt=c.x+R;
}
ld calcup(){//x=now
ld l=fabs(now-c.x);
if(l>=r) return c.y;
return c.y+sqrt(r*r-l*l+1e-8);
}
ld calcdown(){//x=now
ld l=fabs(now-c.x);
if(l>=r) return c.y;
return c.y-sqrt(r*r-l*l+1e-8)-1e-10;
}
}c[100005];
int cnt1,cnt2;
LL w[100005];
int to1[100005],to2[100005];
bool type[100005];
ld calcup(int x){
if(x<=n){
if(type[x]) return p[to1[x]].calcup();
else return c[to2[x]].calcup();
}else{
x-=n;
if(type[x]) return p[to1[x]].calcdown();
else return c[to2[x]].calcdown();
}
}
struct N{
int x;
friend bool operator < (const N&a,const N&b){
return calcup(a.x)>calcup(b.x);
}
N(int a=0){
x=a;
}
};
set<N> st;
int root;
int H[100005],X[100005],P[100005],tot,fa[100005];
inline void add(int x,int y){
x++;y++;
P[++tot]=y;X[tot]=H[x];H[x]=tot;
}
struct Cmpp{
ld x;int id;
int type;// +1 -1
friend bool operator < (Cmpp a,Cmpp b){
if(fabs(a.x-b.x)<1e-8) return a.type>b.type;
return a.x<b.x;
}
Cmpp(ld a=0,int b=0,int c=0){
x=a,id=b,type=c;
}
}list[400005];
ld calcnow(Cmpp a){
if(type[a.id]){
if(a.type==1){
return p[to1[a.id]].lft;
}else{
return p[to1[a.id]].rgt;
}
}else{
if(a.type==1){
return c[to2[a.id]].lft;
}else{
return c[to2[a.id]].rgt;
}
}
}
int num;
Point ask[200005];
int pos[200005];
int cc;
struct Q{
int type;
LL x,y;
}q[200005];
LL sum[400005];
int dfn[200005],top[200005],son[200005],siz[200005],tim,dep[200005];
void dfs(int x){
// printf("#@%d\n",x);
siz[x]=1;
int mx=-1;
dep[x]=dep[fa[x]]+1;
for(int i=H[x];i;i=X[i]){
fa[P[i]]=x;
dfs(P[i]);
siz[x]+=siz[P[i]];
if(siz[P[i]]>mx){
son[x]=P[i];
}
}
}
void dfs2(int x){
if(!top[x]) top[x]=x;
dfn[x]=++tim;
if(son[x]) top[son[x]]=top[x],dfs2(son[x]);
for(int i=H[x];i;i=X[i]){
if(P[i]!=son[x]) dfs2(P[i]);
}
}
int where[200005];
void bd(int o,int l,int r){
if(l==r){
sum[o]=w[where[l]];
}else{
int mid=(l+r)>>1;
bd(o<<1,l,mid);bd(o<<1|1,mid+1,r);
sum[o]=sum[o<<1]^sum[o<<1|1];
}
}
void cg(int o,int l,int r,int pos,LL d){
if(l==r){
sum[o]=d;
}else{
int mid=(l+r)>>1;
if(pos<=mid) cg(o<<1,l,mid,pos,d);
else cg(o<<1|1,mid+1,r,pos,d);
sum[o]=sum[o<<1]^sum[o<<1|1];
}
}
LL Ask(int o,int l,int r,int L,int R){
if(l==L&&r==R){
return sum[o];
}else{
int mid=(l+r)>>1;
if(R<=mid) return Ask(o<<1,l,mid,L,R);
else if(L>mid) return Ask(o<<1|1,mid+1,r,L,R);
else return Ask(o<<1,l,mid,L,mid)^Ask(o<<1|1,mid+1,r,mid+1,R);
}
}
int main(){
// freopen("ot.txt","r",stdin);
// freopen("ot2.txt","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",s);
if(s[0]=='P'){
++cnt1;
p[cnt1].read(i);
type[i]=1;
to1[i]=cnt1;
}else{
++cnt2;
c[cnt2].read(i);
to2[i]=cnt2;
}
scanf("%lld",&w[i+1]);
}
// printf("### %.2f\n",(double)p[1].rgt);
for(int i=1;i<=m;i++){
scanf("%s",s);
if(s[0]=='Q'){
ask[++cc].read();
q[i].x=cc;
ask[++cc].read();
q[i].y=cc;
}else{
q[i].type=1;
scanf("%lld%lld",&q[i].x,&q[i].y);
}
}
// printf("## %d\n",cnt1);
// for(int i=1;i<=cnt1;i++) printf("%u %u\n",p[i].up.size(),p[i].down.size());
for(int i=1;i<=cc;i++) list[num++]=Cmpp(ask[i].x,i,0);
for(int i=1;i<=cnt1;i++) list[num++]=Cmpp(p[i].lft,p[i].id,1),list[num++]=Cmpp(p[i].rgt,p[i].id,-1);
for(int i=1;i<=cnt2;i++) list[num++]=Cmpp(c[i].lft,c[i].id,1),list[num++]=Cmpp(c[i].rgt,c[i].id,-1);
sort(list,list+num);
for(int i=0;i<num;i++){
if(!list[i].type){
now=ask[list[i].id].x;
if(!st.size()){
pos[list[i].id]=0;
}else{
c[0].c=ask[list[i].id];
set<N>::iterator it=st.upper_bound(N(0));
if(it==st.begin()){
pos[list[i].id]=0;
}else{
--it;
if(it->x>n){
pos[list[i].id]=fa[it->x-n];
}else pos[list[i].id]=it->x;
}
}
continue;
}
// printf("# %d\n",list[i].id);
if(list[i].type==1){
now=calcnow(list[i])+1e-10;
// printf("tim: %.2f\n",(double)now);
int sizz=st.size();
if(!st.size()){
// puts("empty");
add(root,list[i].id);
st.insert(N(list[i].id));
st.insert(N(list[i].id+n));
}else{
set<N>::iterator it=st.upper_bound(N(list[i].id));
if(it==st.begin()){
add(root,list[i].id);
st.insert(N(list[i].id));
st.insert(N(list[i].id+n));
}else{
it--;
// printf("%d\n",it->x);
if(it->x>n){
fa[list[i].id]=fa[it->x-n];
add(fa[list[i].id],list[i].id);
st.insert(N(list[i].id));
st.insert(N(list[i].id+n));
}else{
fa[list[i].id]=it->x;
add(fa[list[i].id],list[i].id);
st.insert(N(list[i].id));
st.insert(N(list[i].id+n));
}
}
}
}else{
// continue;
// if(now<2762779) goto ed;
// printf("%u\n",st.size());
// now=calcnow(list[i])-1e-8;
// printf("####%.2f\n",(double) now);
// for(set<N>::iterator it=st.begin();it!=st.end();it++){
// printf("%d ",it->x);
// }
// puts("");
// ed:;
set<N>::iterator it=st.upper_bound(N(list[i].id));
it--;
// printf("%d DELET %d\n",list[i].id,it->x);
if(list[i].id!=it->x) break;
st.erase(it);
it=st.upper_bound(N(list[i].id+n));
it--;
// printf("%d DELET %d\n",list[i].id,it->x-n);
if(list[i].id!=it->x-n) break;
st.erase(it);
}
}
//////////////////////////////////////////////////
//puts("HHHHHHHHHHHHHHHHHHHH");
memset(fa,0,sizeof fa);
for(int i=1;i<=cc;i++) pos[i]++;
root=1;
dfs(root);dfs2(root);
n++;
for(int i=1;i<=n;i++) where[dfn[i]]=i;
bd(1,1,n);
LL ans=0;//printf("s%lld\n",sum[1]);
for(int i=1;i<=m;i++){
if(q[i].type){
cg(1,1,n,dfn[q[i].x+1],q[i].y);
// printf("s%lld\n",sum[1]);
}else{
int x=pos[q[i].x],y=pos[q[i].y];
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans^=Ask(1,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(x!=y) ans^=Ask(1,1,n,dfn[y]+1,dfn[x]);
printf("%lld\n",ans);
}
}
return 0;
}